Delete keys from resource values/overrides handled in fuel2

Keys deletion for values/overrides handled.
Default cliff formatter used for values/overrides operations.
Message on values/overrides set command added.

Change-Id: Ie47ff6a1cb98764447d045816ea6472a0701dcc3
Closes-Bug: #1622600
This commit is contained in:
Alexander Kislitsky 2016-09-12 17:38:44 +03:00
parent 5502205a27
commit db53fcb187
4 changed files with 155 additions and 28 deletions

View File

@ -51,7 +51,9 @@ nailgun.extensions =
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
@ -70,7 +72,9 @@ tuning_box.cli =
fuelclient =
config_get = tuning_box.fuelclient:Get
config_set = tuning_box.fuelclient:Set
config_del = tuning_box.fuelclient:Delete
config_override = tuning_box.fuelclient:Override
config_rm_override = tuning_box.fuelclient:DeleteOverride
config_env_create = tuning_box.fuelclient:CreateEnvironment
config_env_list = tuning_box.fuelclient:ListEnvironments
config_env_show = tuning_box.fuelclient:ShowEnvironment

View File

@ -11,9 +11,13 @@
# under the License.
import json
import six
import yaml
from tuning_box.cli import base
from cliff import show
from fuelclient.cli import error as fc_error
from fuelclient.common import data_utils
from tuning_box.cli.base import BaseCommand
from tuning_box.cli.base import level_converter
@ -22,20 +26,20 @@ class ResourcesCommand(BaseCommand):
def get_parser(self, *args, **kwargs):
parser = super(ResourcesCommand, self).get_parser(*args, **kwargs)
parser.add_argument(
'--env',
'-e', '--env',
type=int,
required=True,
help="ID of environment to get data from",
)
parser.add_argument(
'--level',
'-l', '--level',
type=level_converter,
default=[],
help=("Level to get data from. Should be in format "
"parent_level=parent1,level=value2"),
)
parser.add_argument(
'--resource',
'-r', '--resource',
type=str,
required=True,
help="Name or ID of resource to get data from",
@ -51,53 +55,59 @@ class ResourcesCommand(BaseCommand):
)
class Get(base.FormattedCommand, ResourcesCommand):
class Get(show.ShowOne, ResourcesCommand):
def get_parser(self, *args, **kwargs):
parser = super(Get, self).get_parser(*args, **kwargs)
parser.add_argument(
'--key',
'-k', '--key',
type=str,
help="Name of key to get from the resource",
)
return parser
def take_action(self, parsed_args):
res = self.get_client().get(
response = self.get_client().get(
self.get_resource_url(parsed_args),
params='effective',
)
key = parsed_args.key
if key is None:
return res
value = res[key]
if parsed_args.format != 'plain':
return {key: value}
if key is not None:
result = {key: response.get(key, {})}
else:
return value
result = response
columns = sorted(result.keys())
try:
data = data_utils.get_display_data_single(columns, result)
return columns, data
except fc_error.BadDataException:
return zip(*response.items())
class Set(ResourcesCommand):
url_last_part = 'values'
entity_name = 'ResourceValue'
def get_parser(self, *args, **kwargs):
parser = super(Set, self).get_parser(*args, **kwargs)
parser.add_argument(
'--key',
'-k', '--key',
type=str,
help="Name of key to set in the resource",
)
parser.add_argument(
'--value',
'-v', '--value',
type=str,
help="Value for a key to set in the resource",
)
parser.add_argument(
'--type',
'-t', '--type',
choices=('null', 'int', 'str', 'json', 'yaml', 'bool'),
help="Type of value passed in --value",
)
parser.add_argument(
'--format',
'-f', '--format',
choices=('json', 'yaml'),
help="Format of data passed to stdin",
)
@ -165,6 +175,14 @@ class Set(ResourcesCommand):
return doc
assert False, "Shouldn't get here"
def get_update_message(self, parsed_args):
if parsed_args.key is None:
message = '{0} was set\n'.format(self.entity_name)
else:
message = '{0} for key {1} was set\n'.format(
self.entity_name, parsed_args.key)
return message
def take_action(self, parsed_args):
self.verify_arguments(parsed_args)
value = self.get_value_to_set(parsed_args)
@ -176,8 +194,50 @@ class Set(ResourcesCommand):
resource[parsed_args.key] = value
else:
resource = value
client.put(resource_url, resource)
result = client.put(resource_url, resource)
if result is None:
result = self.get_update_message(parsed_args)
self.app.stdout.write(six.text_type(result))
class Delete(ResourcesCommand):
url_last_part = 'values'
entity_name = 'ResourceValue'
def get_parser(self, *args, **kwargs):
parser = super(Delete, self).get_parser(*args, **kwargs)
parser.add_argument(
'-k', '--key',
type=str,
help="Name of key to delete from the resource",
required=True
)
return parser
def get_deletion_message(self, parsed_args):
return '{0} for key {1} was deleted\n'.format(
self.entity_name, parsed_args.key)
def get_resource_url(self, parsed_args, last_part='values'):
url = super(Delete, self).get_resource_url(
parsed_args, last_part=last_part)
return url + '/keys/delete'
def take_action(self, parsed_args):
client = self.get_client()
resource_url = self.get_resource_url(parsed_args, self.url_last_part)
result = client.patch(resource_url, [[parsed_args.key]])
if result is None:
result = self.get_deletion_message(parsed_args)
self.app.stdout.write(six.text_type(result))
class Override(Set):
url_last_part = 'overrides'
entity_name = 'ResourceOverride'
class DeleteOverride(Delete):
url_last_part = 'overrides'
entity_name = 'ResourceOverride'

View File

@ -53,10 +53,18 @@ class Set(FuelBaseCommand, resources.Set):
pass
class Delete(FuelBaseCommand, resources.Delete):
pass
class Override(FuelBaseCommand, resources.Override):
pass
class DeleteOverride(FuelBaseCommand, resources.DeleteOverride):
pass
class CreateEnvironment(FuelBaseCommand, environments.CreateEnvironment):
pass

View File

@ -50,13 +50,13 @@ class TestGet(testscenarios.WithScenarios, _BaseCLITest):
for s in [
('global,json', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1',
'{"hello": "world"}',
'get --env 1 --resource 1 --format=json',
'{\n "hello": "world"\n}',
)),
('lowlevel,json', (
'/environments/1/lvl1/value1/resources/1/values?effective',
'get --env 1 --level lvl1=value1 --resource 1',
'{"hello": "world"}',
'get --env 1 --level lvl1=value1 --resource 1 --format=json',
'{\n "hello": "world"\n}',
)),
('global,yaml', (
'/environments/1/resources/1/values?effective',
@ -68,21 +68,26 @@ class TestGet(testscenarios.WithScenarios, _BaseCLITest):
'get --env 1 --level lvl1=value1 --resource 1 --format yaml',
'hello: world\n',
)),
('key,plain', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --key hello --format plain',
'world',
)),
('key,json', (
'/environments/1/resources/1/values?effective',
'get --env 1 --resource 1 --key hello --format json',
'{"hello": "world"}',
'{\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",
))
]
]
@ -147,6 +152,56 @@ class TestSet(testscenarios.WithScenarios, _BaseCLITest):
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")),
]
]
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")),
]
]
args = None
expected_body = None
url_last_part = 'overrides'
cmd = 'rm override'
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())