Force loading of tuningbox.cli entry points removed

The force loading of entry points inside the Python code affects
order of loaded entry points. In this case we have wrong
entry points loaded if python-clifftab package is installed.
Unrequired entry points 'tuningbox.cli' removed.
Unused tests removed.
Client tests refactored.

Change-Id: Iea22c6c7539b89025de229a360bca08918219766
Closes-Bug: #1628508
This commit is contained in:
Alexander Kislitsky 2016-10-03 18:50:58 +03:00
parent bb6c1932a4
commit d045bd2010
12 changed files with 587 additions and 749 deletions

View File

@ -48,27 +48,6 @@ output_file = tuning_box/locale/tuning_box.pot
[entry_points]
nailgun.extensions =
tuning_box = tuning_box.nailgun:Extension
tuning_box.cli =
get = tuning_box.cli.resources:Get
set = tuning_box.cli.resources:Set
del = tuning_box.cli.resources:Delete
override = tuning_box.cli.resources:Override
rm_override = tuning_box.cli.resources:DeleteOverride
env_create = tuning_box.cli.environments:CreateEnvironment
env_list = tuning_box.cli.environments:ListEnvironments
env_show = tuning_box.cli.environments:ShowEnvironment
env_delete = tuning_box.cli.environments:DeleteEnvironment
env_update = tuning_box.cli.environments:UpdateEnvironment
comp_create = tuning_box.cli.components:CreateComponent
comp_list = tuning_box.cli.components:ListComponents
comp_show = tuning_box.cli.components:ShowComponent
comp_delete = tuning_box.cli.components:DeleteComponent
comp_update = tuning_box.cli.components:UpdateComponent
def_create = tuning_box.cli.resource_definitions:CreateResourceDefinition
def_list = tuning_box.cli.resource_definitions:ListResourceDefinitions
def_show = tuning_box.cli.resource_definitions:ShowResourceDefinition
def_delete = tuning_box.cli.resource_definitions:DeleteResourceDefinition
def_update = tuning_box.cli.resource_definitions:UpdateResourceDefinition
fuelclient =
config_get = tuning_box.fuelclient:Get
config_set = tuning_box.fuelclient:Set

View File

@ -1,27 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from cliff import app
from cliff import commandmanager
import tuning_box
class TuningBoxApp(app.App):
def __init__(self, client, **kwargs):
super(TuningBoxApp, self).__init__(
description='Tuning Box - configuration storage for your cloud',
version=tuning_box.__version__,
command_manager=commandmanager.CommandManager('tuning_box.cli'),
**kwargs
)
self.client = client

View File

@ -38,26 +38,6 @@ except NameError:
text_type = str
def format_output(output, format_):
if format_ == 'plain':
if output is None:
return ''
if isinstance(output, text_type):
if text_type is str:
return output
else:
return output.encode('utf-8')
format_ = 'json'
# numbers, booleans, lists and dicts will be represented as JSON
if format_ == 'json':
return json.dumps(output)
if format_ == 'yaml':
# Usage of safe_dump here is crucial since PyYAML emits
# "!!python/unicode" objects from unicode strings by defaul
return yaml.safe_dump(output, default_flow_style=False)
raise RuntimeError("Unknown format '{}'".format(format_))
class BaseCommand(command.Command):
def get_client(self):
@ -144,22 +124,3 @@ class BaseShowCommand(BaseOneCommand, show.ShowOne):
return self.columns, data
except fc_error.BadDataException:
return zip(*result.items())
class FormattedCommand(BaseCommand):
format_choices = ('json', 'yaml', 'plain')
def get_parser(self, *args, **kwargs):
parser = super(FormattedCommand, self).get_parser(*args, **kwargs)
parser.add_argument(
'-f', '--format',
choices=self.format_choices,
default='json',
help="Desired format for return value",
)
return parser
def run(self, parsed_args):
res = self.take_action(parsed_args)
self.app.stdout.write(format_output(res, parsed_args.format))
return 0

View File

@ -77,7 +77,7 @@ class ModifyResourceDefinitionCommand(ResourceDefinitionsCommand):
)
return parser
def verify_arguments(self, parsed_args):
def verify_arguments(self, parsed_args, is_creation=True):
if parsed_args.content is not None:
if parsed_args.data_format is not None:
raise errors.IncompatibleParams(
@ -89,15 +89,21 @@ class ModifyResourceDefinitionCommand(ResourceDefinitionsCommand):
"You should specify --type if you pass "
"content in command line."
)
elif parsed_args.data_format is None:
raise errors.IncompatibleParams(
"You should specify --data-format for stdin data if you "
"don't pass content in command line."
)
elif is_creation:
if parsed_args.data_format is None:
raise errors.IncompatibleParams(
"You should specify --data-format for stdin data if you "
"don't pass content in command line."
)
elif parsed_args.type is not None:
raise errors.IncompatibleParams(
"You shouldn't specify --type if you don't pass "
"content in command line."
)
elif parsed_args.type is not None:
raise errors.IncompatibleParams(
"--type and --data-format parameters can't "
"be used together."
"You shouldn't specify --type if you don't pass "
"content in command line."
)
def get_content(self, parsed_args):
@ -135,6 +141,7 @@ class UpdateResourceDefinition(ModifyResourceDefinitionCommand,
base.BaseOneCommand):
def take_action(self, parsed_args):
self.verify_arguments(parsed_args, is_creation=False)
data = {}
if parsed_args.name is not None:
data['name'] = parsed_args.name

View File

@ -17,6 +17,7 @@ import yaml
from cliff import show
from fuelclient.cli import error as fc_error
from fuelclient.common import data_utils
from tuning_box.cli import errors
from tuning_box.cli.base import BaseCommand
from tuning_box.cli.base import level_converter
@ -125,30 +126,35 @@ class Set(ResourcesCommand):
def verify_arguments(self, parsed_args):
if parsed_args.key is None: # no key
if parsed_args.value is not None or parsed_args.type is not None:
raise Exception("--value and --type arguments make sense only "
"with --key argument.")
raise errors.IncompatibleParams(
"--value and --type arguments make sense only "
"with --key argument.")
if parsed_args.format is None:
raise Exception("Please specify format of data passed to stdin"
" to replace whole resource data.")
raise errors.IncompatibleParams(
"Please specify format of data passed to stdin"
" to replace whole resource data.")
elif parsed_args.value is not None: # have key and value
if parsed_args.format is not None:
raise Exception("You shouldn't specify --format if you pass "
"value in command line, specify --type "
"instead.")
raise errors.IncompatibleParams(
"You shouldn't specify --format if you pass "
"value in command line, specify --type instead.")
if parsed_args.type == 'null':
raise Exception("You shouldn't specify a value for 'null' type"
" because there can be only one.")
raise errors.IncompatibleParams(
"You shouldn't specify a value for 'null' type "
"because there can be only one.")
if parsed_args.type is None:
raise Exception("Please specify type of value passed in "
"--value argument to properly represent it"
" in the storage.")
raise errors.IncompatibleParams(
"Please specify type of value passed in --value argument "
"to properly represent it in the storage.")
elif parsed_args.type != 'null': # have key but no value
if parsed_args.type is not None:
raise Exception("--type specifies type for value provided in "
"--value but there is not --value argument")
raise errors.IncompatibleParams(
"--type specifies type for value provided in --value "
"but there is not --value argument")
if parsed_args.format is None:
raise Exception("Please specify format of data passed to stdin"
" to replace the key.")
raise errors.IncompatibleParams(
"Please specify format of data passed to stdin "
"to replace the key.")
def get_value_to_set(self, parsed_args):
type_ = parsed_args.type

View File

@ -12,10 +12,8 @@
from __future__ import absolute_import
from cliff import command
from fuelclient import client as fc_client
from tuning_box import cli
from tuning_box.cli import base as cli_base
from tuning_box.cli import components
from tuning_box.cli import environments
@ -145,15 +143,3 @@ class UpdateResourceDefinition(
resource_definitions.UpdateResourceDefinition
):
pass
class Config(command.Command):
def get_parser(self, *args, **kwargs):
parser = super(Config, self).get_parser(*args, **kwargs)
parser.add_argument('args', nargs='*')
return parser
def take_action(self, parsed_args):
client = FuelHTTPClient()
app = cli.TuningBoxApp(client)
app.run(parsed_args.args)

View File

@ -10,55 +10,19 @@
# License for the specific language governing permissions and limitations
# under the License.
from requests_mock.contrib import fixture as req_fixture
import unittest
from cliff import app
from cliff import commandmanager
import six
import testscenarios
from tuning_box import cli
from tuning_box.cli import base as cli_base
from tuning_box import client as tb_client
from tuning_box.tests import base
class FormatOutputTest(testscenarios.WithScenarios, base.TestCase):
scenarios = [
(s[0], dict(zip(('output', 'format_', 'expected_result'), s[1])))
for s in [
('none,plain', (None, 'plain', '')),
('none,json', (None, 'json', 'null')),
# TODO(yorik-sar): look into why YAML return those elipsis
('none,yaml', (None, 'yaml', 'null\n...\n')),
('str,plain', (u"a string", 'plain', 'a string')),
('str,json', (u"a string", 'json', '"a string"')),
('str,yaml', (u"a string", 'yaml', 'a string\n...\n')),
('int,plain', (42, 'plain', '42')),
('int,json', (42, 'json', '42')),
('int,yaml', (42, 'yaml', '42\n...\n')),
('float,plain', (1.2, 'plain', '1.2')),
('float,json', (1.2, 'json', '1.2')),
('float,yaml', (1.2, 'yaml', '1.2\n...\n')),
('list,plain', ([1, 2], 'plain', '[1, 2]')),
('list,json', ([1, 2], 'json', '[1, 2]')),
('list,yaml', ([1, 2], 'yaml', '- 1\n- 2\n')),
('dict,plain', ({'a': 1}, 'plain', '{"a": 1}')),
('dict,json', ({'a': 1}, 'json', '{"a": 1}')),
('dict,yaml', ({'a': 1}, 'yaml', 'a: 1\n')),
]
]
output = None
format_ = None
expected_result = None
def test_format_output(self):
res = cli_base.format_output(self.output, self.format_)
self.assertEqual(self.expected_result, res)
class SafeTuningBoxApp(cli.TuningBoxApp):
def __init__(self, client):
class SafeTuningBoxApp(app.App):
def __init__(self):
super(SafeTuningBoxApp, self).__init__(
client=client,
description='Tuning Box - configuration storage for your cloud',
version='',
command_manager=commandmanager.CommandManager('fuelclient'),
**self.get_std_streams()
)
@ -70,30 +34,9 @@ class SafeTuningBoxApp(cli.TuningBoxApp):
io_cls = six.StringIO
return {k: io_cls() for k in ('stdin', 'stdout', 'stderr')}
def build_option_parser(self, description, version, argparse_kwargs=None):
parser = super(SafeTuningBoxApp, self).build_option_parser(
description, version, argparse_kwargs)
parser.set_defaults(debug=True)
return parser
def get_fuzzy_matches(self, cmd):
# Turn off guessing, we need exact failures in tests
return []
class BaseCommandTest(unittest.TestCase):
def run(self, argv):
try:
super(SafeTuningBoxApp, self).run(argv)
except SystemExit as e:
# We should check exit code only if system exit was called.
exit_code = e.code
assert exit_code == 0
class _BaseCLITest(base.TestCase):
BASE_URL = 'http://somehost/prefix'
def setUp(self):
super(_BaseCLITest, self).setUp()
client = tb_client.HTTPClient(self.BASE_URL)
self.req_mock = self.useFixture(req_fixture.Fixture())
self.cli = SafeTuningBoxApp(client=client)
@property
def parser(self):
return self.cmd.get_parser(None)

View File

@ -10,136 +10,138 @@
# License for the specific language governing permissions and limitations
# under the License.
import testscenarios
import mock
from tuning_box.tests.cli import _BaseCLITest
from tuning_box.cli import base as cli_base
from tuning_box.cli import components
from tuning_box.tests import cli as tests_cli
class TestCreateComponent(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('json', ('/components',
'comp create --name comp_name --format json',
'{\n "a": "b"\n}')),
('yaml', ('/components',
'comp create -n comp_name -f yaml',
'a: b\n')),
class TestCreateComponent(tests_cli.BaseCommandTest):
cmd = components.CreateComponent(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
(),
('-na',),
('-na', '-fjson'),
('-na', '-fyaml'),
('-na', '-ftable'),
('-na', '-fshell'),
('-na', '-fvalue'),
('--name=a', '--format=json')
]
]
for params in params_set:
self.parser.parse_args(params)
mock_url = None
args = None
expected_result = None
def test_post(self):
self.req_mock.post(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={'a': 'b'},
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(('-na',))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.post.return_value = {'a': 1, 'b': 2}
self.cmd.run(parsed_params)
m_client.post.assert_called_with(
'/components',
{'resource_definitions': [], 'name': 'a'}
)
class TestListComponents(testscenarios.WithScenarios, _BaseCLITest):
class TestListComponents(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('json', ('/components', 'comp list -f json', '[]')),
('yaml', ('/components', 'comp list --format yaml', '[]\n')),
cmd = components.ListComponents(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-fjson',),
('-fyaml',),
('-ftable',),
('-fvalue',),
('-fcsv',),
('-cid',),
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
self.parser.parse_args(params)
def test_get(self):
self.req_mock.get(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json=[],
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(())
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.get.return_value = [
{'id': 1, 'resource_definitions': [1, 2], 'name': 'n'}
]
self.cmd.run(parsed_params)
m_client.get.assert_called_with('/components')
class TestShowComponent(testscenarios.WithScenarios, _BaseCLITest):
class TestShowComponent(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('yaml', ('/components/9', 'comp show 9 -f yaml',
'id: 1\nname: n\nresource_definitions: []\n')),
cmd = components.ShowComponent(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-fjson', '1'),
('-fyaml', '1'),
('-ftable', '1'),
('-fvalue', '1'),
('-fshell', '1'),
('-cid', '1'),
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
self.parser.parse_args(params)
def test_get(self):
self.req_mock.get(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={'id': 1, 'name': 'n', 'resource_definitions': []},
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(('3',))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.get.return_value = {'id': 1, 'name': 'n',
'resource_definitions': [1, 2]}
self.cmd.run(parsed_params)
m_client.get.assert_called_with('/components/3')
class TestDeleteComponent(testscenarios.WithScenarios, _BaseCLITest):
class TestDeleteComponent(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('', ('/components/9', 'comp delete 9',
'Component with id 9 was deleted\n')),
cmd = components.DeleteComponent(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [('1',)]
for params in params_set:
self.parser.parse_args(params)
def test_result(self):
parsed_params = self.parser.parse_args(('3',))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
self.cmd.run(parsed_params)
m_client.delete.assert_called_with('/components/3')
class TestUpdateComponent(tests_cli.BaseCommandTest):
cmd = components.UpdateComponent(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('1',),
('-r[]', '1'),
('-r1,2', '1'),
('-na', '-r1,2', '1')
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
self.parser.parse_args(params)
def test_delete(self):
self.req_mock.delete(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'}
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
class TestUpdateComponent(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('no_data', ('/components/9', 'comp update 9', '{}')),
('s_name', ('/components/9',
'comp update 9 -n comp_name', '{}')),
('l_name', ('/components/9',
'comp update 9 --name comp_name', '{}')),
('s_r_defs', ('/components/9',
'comp update 9 -r 1,2 ', '{}')),
('l_r_ders', ('/components/9',
'comp update 9 --resource-definitions 1,2', '{}')),
('empty_s_r_defs', ('/components/9',
'comp update 9 -r [] -n comp_name', '{}')),
('empty_l_r_defs', ('/components/9',
'comp update 9 --resource-definitions []',
'{}'))
]
]
mock_url = None
args = None
expected_result = None
def test_update(self):
self.req_mock.patch(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={}
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(('-na', '-r[]', '1'))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
self.cmd.run(parsed_params)
m_client.patch.assert_called_with(
'/components/1',
{'name': 'a', 'resource_definitions': []}
)

View File

@ -10,144 +10,137 @@
# License for the specific language governing permissions and limitations
# under the License.
import testscenarios
import mock
from tuning_box.tests.cli import _BaseCLITest
from tuning_box.cli import base as cli_base
from tuning_box.cli import environments as env
from tuning_box.tests import cli as tests_cli
class TestCreateEnvironment(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('json', ('/environments',
'env create -l lvl1 -i 1 -f json',
'{\n "a": "b"\n}')),
('yaml', ('/environments',
'env create -l lvl1,lvl2 -i 1 -f yaml',
'a: b\n')),
('multi', ('/environments',
'env create -l lvl1,lvl2 -i 1,2,3 -f yaml',
'a: b\n')),
('no_data', ('/environments',
'env create -f yaml',
'a: b\n'))
class TestCreateEnvironment(tests_cli.BaseCommandTest):
cmd = env.CreateEnvironment(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
(),
('-i1',),
('-i1,2',),
('-i1', '-llvl1'),
('-i1', '-llvl1,lvl2'),
('--components=1,2', '--levels=lvl1,lvl2')
]
]
for params in params_set:
self.parser.parse_args(params)
mock_url = None
args = None
expected_result = None
def test_post(self):
self.req_mock.post(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={'a': 'b'},
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(('-i1', '-llvl1,lvl2'))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.post.return_value = {'a': 1, 'b': 2}
self.cmd.run(parsed_params)
m_client.post.assert_called_with(
'/environments',
{'hierarchy_levels': ['lvl1', 'lvl2'], 'components': [1]}
)
class TestListEnvironments(testscenarios.WithScenarios, _BaseCLITest):
class TestListEnvironments(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('json', ('/environments', 'env list -f json', '[]')),
('yaml', ('/environments', 'env list -f yaml', '[]\n'))
cmd = env.ListEnvironments(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-fjson',),
('-fyaml',),
('-ftable',),
('-fvalue',),
('-fcsv',),
('-cid',),
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
self.parser.parse_args(params)
def test_get(self):
self.req_mock.get(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={},
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(())
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.get.return_value = [
{'id': 1, 'hierarchy_levels': [], 'components': [1, 2]}
]
self.cmd.run(parsed_params)
m_client.get.assert_called_with('/environments')
class TestShowEnvironment(testscenarios.WithScenarios, _BaseCLITest):
class TestShowEnvironment(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('json', ('/environments/9', 'env show 9 -f json -c id',
'{\n "id": 1\n}')),
('yaml', ('/environments/9', 'env show 9 -f yaml -c id',
'id: 1\n'))
cmd = env.ShowEnvironment(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-fjson', '1'),
('-fyaml', '1'),
('-ftable', '1'),
('-fvalue', '1'),
('-fshell', '1'),
('-cid', '1'),
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
self.parser.parse_args(params)
def test_get(self):
self.req_mock.get(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={'id': 1},
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(('3',))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.get.return_value = {'id': 1, 'hierarchy_levels': [],
'components': [1, 2]}
self.cmd.run(parsed_params)
m_client.get.assert_called_with('/environments/3')
class TestDeleteEnvironment(testscenarios.WithScenarios, _BaseCLITest):
class TestDeleteEnvironment(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('json', ('/environments/9', 'env delete 9',
'Environment with id 9 was deleted\n'))
cmd = env.DeleteEnvironment(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [('1',)]
for params in params_set:
self.parser.parse_args(params)
def test_result(self):
parsed_params = self.parser.parse_args(('3',))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
self.cmd.run(parsed_params)
m_client.delete.assert_called_with('/environments/3')
class TestUpdateEnvironment(tests_cli.BaseCommandTest):
cmd = env.UpdateEnvironment(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('1',),
('-l[]', '1'),
('-llvl1', '-i1', '1'),
('-llvl1,lvl2', '-i1', '1'),
('-llvl1,lvl2', '-i1,2', '1')
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
self.parser.parse_args(params)
def test_delete(self):
self.req_mock.delete(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'}
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
class TestUpdateEnvironment(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('no_data', ('/environments/9', 'env update 9', '{}')),
('level', ('/environments/9', 'env update 9 -l lvl1', '{}')),
('levels', ('/environments/9',
'env update 9 -l lvl1,lvl2',
'{}')),
('component', ('/environments/9',
'env update 9 -l lvl1,lvl2 -i 1',
'{}')),
('components', ('/environments/9',
'env update 9 -l lvl1,lvl2 -i 1,2',
'{}')),
('erase', ('/environments/9', 'env update 9 -l [] -i 1,2', '{}')),
('erase', ('/environments/9', 'env update 9 -l [] -i []', '{}')),
]
]
mock_url = None
args = None
expected_result = None
def test_update(self):
self.req_mock.patch(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={}
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(('-i1', '-l[]', '1'))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
self.cmd.run(parsed_params)
m_client.patch.assert_called_with(
'/environments/1',
{'hierarchy_levels': [], 'components': [1]}
)

View File

@ -1,20 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from tuning_box.tests.cli import _BaseCLITest
class TestApp(_BaseCLITest):
def test_help(self):
self.cli.run(["--help"])
self.assertEqual('', self.cli.stderr.getvalue())
self.assertNotIn('Could not', self.cli.stdout.getvalue())

View File

@ -10,141 +10,183 @@
# License for the specific language governing permissions and limitations
# under the License.
import testscenarios
import yaml
import io
import json
from tuning_box.tests.cli import _BaseCLITest
import mock
from tuning_box.cli import base as cli_base
from tuning_box.cli import errors
from tuning_box.cli import resource_definitions as res_def
from tuning_box.tests import cli as tests_cli
class TestCreateResourceDefinition(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0],
dict(zip(('args', 'expected_body', 'stdin'), s[1])))
for s in [
('json', ('def create -n n -i 1 -d json -f yaml',
'content: {}\ncomponent_id: 1\nid: 1\nname: n\n',
'{"a": 3}')),
('yaml', ('def create -n n -i 1 -d yaml -f yaml',
'content: {}\ncomponent_id: 1\nid: 1\nname: n\n',
'a: b\n')),
class TestCreateResourceDefinition(tests_cli.BaseCommandTest):
cmd = res_def.CreateResourceDefinition(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-nname',),
('-nname', '-fjson'),
('-nname', '-fyaml'),
('-nname', '-djson'),
('-nname', '-dyaml'),
('-nname', '-i1'),
('-nname', '-i1', '-djson'),
('-nname', '-i1', '-tjson', '-pa'),
('--name=a', '--component=1', '--type=json', '--content=a'),
]
]
for params in params_set:
self.parser.parse_args(params)
args = None
expected_body = None
stdin = None
def test_post(self):
url = self.BASE_URL + '/resource_definitions'
self.req_mock.post(
url,
headers={'Content-Type': 'application/json'},
json={'id': 1, 'component_id': 1, 'name': 'n', 'content': {}}
)
if self.stdin:
self.cli.stdin.write(self.stdin)
self.cli.stdin.seek(0)
self.cli.run(self.args.split())
self.assertEqual(
yaml.safe_load(self.expected_body),
yaml.safe_load(self.cli.stdout.getvalue())
)
class TestListResourceDefinitions(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('json', ('/resource_definitions', 'def list -f json', '[]')),
('yaml', ('/resource_definitions', 'def list --format yaml',
'[]\n')),
def test_arguments_constraints(self):
params_set = [
('-na', '-px', '-djson'), # should use type
('-na', '-px'), # should use type
('-na',), # no data format
('-na', '-tjson', '-djson'), # type and content-data
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
parsed_params = self.parser.parse_args(params)
self.assertRaises(errors.IncompatibleParams, self.cmd.run,
parsed_params)
def test_get(self):
self.req_mock.get(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json=[],
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(('-na', '-i1', '-p"aaa"',
'-tjson'))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.post.return_value = {'a': 1, 'b': 2}
self.cmd.run(parsed_params)
m_client.post.assert_called_with(
'/resource_definitions',
{'content': 'aaa', 'component_id': 1, 'name': 'a'}
)
class TestShowComponent(testscenarios.WithScenarios, _BaseCLITest):
class TestListResourceDefinitions(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('yaml', ('/resource_definitions/9', 'def show 9 -f yaml',
'id: 1\nname: n\ncomponent_id: 2\ncontent: {}\n')),
cmd = res_def.ListResourceDefinitions(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-fjson',),
('-fyaml',),
('-ftable',),
('-fvalue',),
('-fcsv',),
('-cid',),
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
self.parser.parse_args(params)
def test_get(self):
self.req_mock.get(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={'id': 1, 'name': 'n', 'component_id': 2, 'content': {}},
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(())
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.get.return_value = [
{'id': 1, 'name': 'n', 'component_id': 1, 'content': 'xx'}
]
self.cmd.run(parsed_params)
m_client.get.assert_called_with('/resource_definitions')
class TestDeleteComponent(testscenarios.WithScenarios, _BaseCLITest):
class TestShowComponent(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('', ('/resource_definitions/9', 'def delete 9',
'Resource_definition with id 9 was deleted\n')),
cmd = res_def.ShowResourceDefinition(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-fjson', '1'),
('-fyaml', '1'),
('-ftable', '1'),
('-fvalue', '1'),
('-fshell', '1'),
('-cid', '1'),
]
]
mock_url = None
args = None
expected_result = None
for params in params_set:
self.parser.parse_args(params)
def test_delete(self):
self.req_mock.delete(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'}
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_result(self):
parsed_params = self.parser.parse_args(('3',))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.get.return_value = {'id': 1, 'name': 'n',
'component_id': 1, 'content': 'xx'}
self.cmd.run(parsed_params)
m_client.get.assert_called_with('/resource_definitions/3')
class TestUpdateResourceDefinition(testscenarios.WithScenarios, _BaseCLITest):
class TestDeleteComponent(tests_cli.BaseCommandTest):
scenarios = [
(s[0], dict(zip(('args', 'expected_result', 'stdin'), s[1])))
for s in [
('no_data', ('def update 9', '{}')),
('name', ('def update 9 -n comp_name', '{}', False)),
('component_id', ('def update 9 -i 1', '{}', False)),
('content', ('def update 9 -p "a" -t yaml', '{}', False)),
('stdin_content', ('def update 9 -d yaml', '{}', 'a: b')),
('stdin_content', ('def update 9 -d yaml', '{}', 'a: b')),
cmd = res_def.DeleteResourceDefinition(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [('1',)]
for params in params_set:
self.parser.parse_args(params)
def test_result(self):
parsed_params = self.parser.parse_args(('3',))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
self.cmd.run(parsed_params)
m_client.delete.assert_called_with('/resource_definitions/3')
class TestUpdateResourceDefinition(tests_cli.BaseCommandTest):
cmd = res_def.UpdateResourceDefinition(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-nname', '1'),
('-nname', '-i1', '1'),
('-nname', '-i1', '-pval', '1'),
('-nname', '-i1', '-pval', '-tjson', '1'),
('-nname', '-i1', '-pval', '-tyaml', '1'),
('-nname', '-i1', '-djson', '1'),
('-nname', '-i1', '-dyaml', '1'),
('--name=a', '--component-id=1', '--type=json',
'--content=a', '1'),
('--name=a', '--component-id=1', '--data-format=json', '1')
]
]
args = None
expected_result = None
stdin = None
for params in params_set:
self.parser.parse_args(params)
def test_update(self):
self.req_mock.patch(
self.BASE_URL + '/resource_definitions/9',
headers={'Content-Type': 'application/json'},
json={}
)
if self.stdin:
self.cli.stdin.write(self.stdin)
self.cli.stdin.seek(0)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
def test_arguments_constraints(self):
params_set = [
('-px', '1'), # no type
('-px', '-djson', '1'), # should use type
('-px', '-djson', '-tjson', '1'), # shouldn't use data-format
('-tjson', '1'), # no content
]
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
data = {'a': 'b'}
json.dump(data, self.cmd.app.stdin)
for params in params_set:
parsed_params = self.parser.parse_args(params)
self.cmd.app.stdin.seek(io.SEEK_SET)
self.assertRaises(errors.IncompatibleParams, self.cmd.run,
parsed_params)
def test_result(self):
parsed_params = self.parser.parse_args(('-na', '-i1', '-p"aaa"',
'-tjson', '1'))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
self.cmd.run(parsed_params)
m_client.patch.assert_called_with(
'/resource_definitions/1',
{'content': 'aaa', 'component_id': 1, 'name': 'a'}
)

View File

@ -10,208 +10,174 @@
# License for the specific language governing permissions and limitations
# under the License.
import testscenarios
import io
import json
import unittest
import mock
from tuning_box.cli import base as cli_base
from tuning_box.tests import base
from tuning_box.tests.cli import _BaseCLITest
from tuning_box.cli import errors
from tuning_box.cli import resources
from tuning_box.tests import cli as tests_cli
class TestLevelsConverter(testscenarios.WithScenarios, base.TestCase):
scenarios = [
(s[0], dict(zip(('input', 'expected_result', 'expected_error'), s[1])))
for s in [
('empty', ('', None, TypeError)),
('one', ('lvl=val', [('lvl', 'val')])),
('two', ('lvl1=val1,lvl2=val2', [('lvl1', 'val1'),
('lvl2', 'val2')])),
('no_eq', ('val', None, TypeError)),
('no_eq2', ('lvl1=val2,val', None, TypeError)),
('two_eq', ('lvl1=foo=baz', [('lvl1', 'foo=baz')])),
]
]
input = None
expected_result = None
expected_error = None
class TestLevelsConverter(unittest.TestCase):
def test_levels(self):
if self.expected_error:
self.assertRaises(
self.expected_error, cli_base.level_converter, self.input)
else:
res = cli_base.level_converter(self.input)
self.assertEqual(self.expected_result, res)
class TestGet(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0], dict(zip(('mock_url', 'args', 'expected_result'), s[1])))
for s in [
('global,json', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --format=json',
'{\n "hello": "world"\n}',
)),
('global,lookup', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --format=json --show-lookup',
'{\n "hello": "world"\n}',
)),
('lowlevel,json', (
'/environments/1/lvl1/value1/resources/1/values?effective',
'get --env 1 --level lvl1=value1 --resource 1 --format=json',
'{\n "hello": "world"\n}',
)),
('global,yaml', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --format yaml',
'hello: world\n',
)),
('lowlevel,yaml', (
'/environments/1/lvl1/value1/resources/1/values?effective',
'get --env 1 --level lvl1=value1 --resource 1 --format yaml',
'hello: world\n',
)),
('key,json', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --key hello --format json',
'{\n "hello": "world"\n}',
)),
('key,lookup', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --key hello --format json -s',
'{\n "hello": "world"\n}',
)),
('key,yaml', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --key hello --format yaml',
'hello: world\n',
)),
('no_key,json', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --key no --format json',
'{\n "no": {}\n}',
)),
('no_key,yaml', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --key no --format yaml',
"'no': {}\n",
))
params_set = [
('lvl=val', [('lvl', 'val')]),
('lvl1=val1,lvl2=val2', [('lvl1', 'val1'), ('lvl2', 'val2')]),
('lvl1=foo=baz', [('lvl1', 'foo=baz')])
]
]
for params, expected in params_set:
actual = cli_base.level_converter(params)
self.assertEqual(actual, expected)
mock_url = None
args = None
expected_result = None
def test_get(self):
self.req_mock.get(
self.BASE_URL + self.mock_url,
headers={'Content-Type': 'application/json'},
json={'hello': 'world'},
)
self.cli.run(self.args.split())
self.assertEqual(self.expected_result, self.cli.stdout.getvalue())
class TestSet(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0],
dict(zip(('args', 'expected_body', 'should_get', 'stdin'), s[1])))
for s in [
('json', ('--format json', {'a': 3}, False, '{"a": 3}')),
('yaml', ('--format yaml', {'a': 3}, False, 'a: 3')),
('key,json', ('--key b --format json', {'a': 1, 'b': {'a': 3}},
True, '{"a": 3}')),
('key,yaml', ('--key b --format yaml', {'a': 1, 'b': {'a': 3}},
True, 'a: 3')),
('key,null', ('--key b --type null', {'a': 1, 'b': None})),
('key,str', ('--key b --type str --value 4', {'a': 1, 'b': '4'})),
def test_levels_failure(self):
params_set = [
('', TypeError),
('val', TypeError),
('lvl1=val2,val', TypeError)
]
]
for params, expected in params_set:
self.assertRaises(expected, cli_base.level_converter, params)
args = None
expected_body = None
should_get = True
stdin = None
url_last_part = 'values'
cmd = 'set'
class TestGet(tests_cli.BaseCommandTest):
def test_set(self):
url = self.BASE_URL + '/environments/1/lvl1/value1/resources/1/' + \
self.url_last_part
self.req_mock.put(url)
if self.should_get:
self.req_mock.get(
url,
headers={'Content-Type': 'application/json'},
json={'a': 1, 'b': True},
cmd = resources.Get(tests_cli.SafeTuningBoxApp(), None)
def test_arguments(self):
params_set = [
('-e1', '-r1'),
('-e1', '-r1', '-fjson'),
('-e1', '-r1', '-fyaml'),
('-e1', '-r1', '-ftable'),
('-e1', '-r1', '-fshell'),
('-e1', '-r1', '-fvalue'),
('-e1', '-r1', '-la=1'),
('-e1', '-r1', '-la=1,b=2'),
('-e1', '-r1', '-la=1,b=2', '-kkey'),
('-e1', '-r1', '-la=1,b=2', '-s'),
('--env=1', '--resource=1', '--format=json', '--level=a=1'
'--key=kk', '--show-lookup'),
]
for params in params_set:
self.parser.parse_args(params)
def test_result(self):
parsed_params = self.parser.parse_args(('-e1', '-r1', '-fjson'))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.get.return_value = {'a': 1, 'b': 2}
self.cmd.run(parsed_params)
m_client.get.assert_called_with(
'/environments/1/resources/1/values',
params={'effective': True}
)
args = [self.cmd] + ("--env 1 --level lvl1=value1 --resource 1 " +
self.args).split()
if self.stdin:
self.cli.stdin.write(self.stdin)
self.cli.stdin.seek(0)
self.cli.run(args)
req_history = self.req_mock.request_history
if self.should_get:
self.assertEqual('GET', req_history[0].method)
self.assertEqual('PUT', req_history[-1].method)
self.assertEqual(self.expected_body, req_history[-1].json())
class TestDelete(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0],
dict(zip(('args', 'expected_body'), s[1])))
for s in [
('k1', ('-k k1', "ResourceValue for key k1 was deleted\n")),
('xx', ('-k xx', "ResourceValue for key xx was deleted\n")),
class TestSet(tests_cli.BaseCommandTest):
cmd = resources.Set(tests_cli.SafeTuningBoxApp(), None)
url_end = 'values'
def test_arguments(self):
params_set = [
('-e1', '-r1'),
('-e1', '-r1', '-fjson'),
('-e1', '-r1', '-fyaml'),
('-e1', '-r1', '-fjson'),
('-e1', '-r1', '-tnull'),
('-e1', '-r1', '-tint'),
('-e1', '-r1', '-tstr'),
('-e1', '-r1', '-tjson'),
('-e1', '-r1', '-tyaml'),
('-e1', '-r1', '-tbool'),
('-e1', '-r1', '-la=1,b=2'),
('-e1', '-r1', '-la=1,b=2', '-kkey'),
('-e1', '-r1', '-la=1,b=2', '-kkey', '-vval'),
('--env=1', '--resource=1', '--level=a=1,b=2', '--key=key',
'--value=val')
]
]
for params in params_set:
self.parser.parse_args(params)
args = None
expected_body = None
url_last_part = 'values'
cmd = 'del'
def test_delete(self):
url = self.BASE_URL + '/environments/1/lvl1/value1/resources/1/' + \
self.url_last_part + '/keys/delete'
self.req_mock.patch(url)
args = [self.cmd] + ("--env 1 --level lvl1=value1 --resource 1 " +
self.args).split()
self.cli.run(args)
self.assertEqual(self.expected_body, self.cli.stdout.getvalue())
class TestOverride(TestSet):
url_last_part = 'overrides'
cmd = 'override'
class TestDeleteOverride(testscenarios.WithScenarios, _BaseCLITest):
scenarios = [
(s[0],
dict(zip(('args', 'expected_body'), s[1])))
for s in [
('k1', ('-k k1', "ResourceOverride for key k1 was deleted\n")),
('xx', ('-k xx', "ResourceOverride for key xx was deleted\n")),
def test_arguments_constraints(self):
params_set = [
('-e1', '-r1', '-tint'), # no key
('-e1', '-r1', '-vval'), # no key
('-e1', '-r1', '-tstr', '-vval'), # no key
('-e1', '-r1', '-kk', '-vval', '-fjson'), # should use type
('-e1', '-r1', '-kk', '-tstr', '-fjson'), # no val
]
]
for params in params_set:
parsed_params = self.parser.parse_args(params)
self.assertRaises(errors.IncompatibleParams, self.cmd.run,
parsed_params)
args = None
expected_body = None
url_last_part = 'overrides'
cmd = 'rm override'
def test_result_no_key(self):
parsed_params = self.parser.parse_args(('-e1', '-r1', '-fjson'))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
data = {'a': 'b'}
json.dump(data, self.cmd.app.stdin)
self.cmd.app.stdin.seek(io.SEEK_SET)
self.cmd.run(parsed_params)
m_client.put.assert_called_with(
'/environments/1/resources/1/{0}'.format(self.url_end),
data
)
def test_delete(self):
url = self.BASE_URL + '/environments/1/lvl1/value1/resources/1/' + \
self.url_last_part + '/keys/delete'
self.req_mock.patch(url)
args = [self.cmd] + ("--env 1 --level lvl1=value1 --resource 1 " +
self.args).split()
self.cli.run(args)
self.assertEqual(self.expected_body, self.cli.stdout.getvalue())
def test_result_with_key(self):
parsed_params = self.parser.parse_args(('-e1', '-r1', '-kkey',
'-tjson', '-v{"a": "b"}'))
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
m_client.get.return_value = {'init': 'value'}
self.cmd.run(parsed_params)
m_client.put.assert_called_with(
'/environments/1/resources/1/{0}'.format(self.url_end),
{'init': 'value', 'key': {'a': 'b'}}
)
class TestOverride(tests_cli.BaseCommandTest):
cmd = resources.Override(tests_cli.SafeTuningBoxApp(), None)
url_end = 'overrides'
class TestDelete(tests_cli.BaseCommandTest):
cmd = resources.Delete(tests_cli.SafeTuningBoxApp(), None)
url_end = 'values'
def test_arguments(self):
params_set = [
('-e1', '-r1', '-la=1,b=2', '-kkey'),
('--env=1', '--resource=1', '--level=a=1', '--key=k'),
]
for params in params_set:
self.parser.parse_args(params)
def test_result(self):
parsed_params = self.parser.parse_args(('-e1', '-r1', '-la=1,b=2',
'-kkey'))
url = '/environments/1/a/1/b/2/resources/1/{0}/keys/delete'.format(
self.url_end)
with mock.patch.object(cli_base.BaseCommand, 'get_client') as client:
m_client = mock.Mock()
client.return_value = m_client
self.cmd.run(parsed_params)
m_client.patch.assert_called_with(url, [['key']])
class TestDeleteOverride(TestDelete):
cmd = resources.DeleteOverride(tests_cli.SafeTuningBoxApp(), None)
url_end = 'overrides'