Allow passing list of dicts for create-vms-conf command.

Previous implementation of command "fuel2 node create-vms-conf"
didn't allow using list of dicts for --conf parameter. It required
to use multiple arguments like:
    --conf '{"id": 1}' '{"id": 2}'
which is non obvious for user and inconsistent with UI (in UI
user sees list of dicts).
This patch introduces new possibility to pass parameters
as json list:
    --conf '[{"id": 1}, {"id": 2}]'

Change-Id: I50e961c1afce91fd1c43d1fdcf6436a08a20c2be
Related-Bug: #1582136
Closes-Bug: #1582120
(cherry-picked from commit 298187d131)
This commit is contained in:
Alexander Saprykin 2016-05-18 13:27:25 +02:00
parent fa053d0768
commit 39f6f5f045
4 changed files with 60 additions and 12 deletions

View File

@ -13,11 +13,13 @@
# under the License.
import collections
import json
import operator
import os
import six
from fuelclient.cli import error
from fuelclient.commands import base
from fuelclient.common import data_utils
from fuelclient import utils
@ -167,7 +169,7 @@ class NodeCreateVMsConf(NodeMixIn, base.BaseCommand):
help='Id of the {0}.'.format(self.entity_name))
parser.add_argument(
'--conf',
type=str,
type=json.loads,
required=True,
nargs='+',
help='JSONs with VMs configuration',
@ -176,7 +178,12 @@ class NodeCreateVMsConf(NodeMixIn, base.BaseCommand):
return parser
def take_action(self, parsed_args):
confs = utils.parse_to_list_of_dicts(parsed_args.conf)
try:
confs = utils.parse_to_list_of_dicts(parsed_args.conf)
except TypeError:
raise error.BadDataException(
'VM configuration should be a dictionary '
'or a list of dictionaries')
data = self.client.node_vms_create(parsed_args.id, confs)
msg = "{0}".format(data)
self.app.stdout.write(msg)

View File

@ -240,3 +240,21 @@ class TestUtils(base.UnitTestCase):
with self.assertRaisesRegexp(error.HTTPError,
'403.*{}'.format(text)):
client.Client().post_request('address')
def test_parse_to_list_of_dicts(self):
items = utils.parse_to_list_of_dicts([{"id": 1}])
self.assertEqual(items, [{"id": 1}])
items = utils.parse_to_list_of_dicts([{"id": 2}, {"id": 3}])
self.assertEqual(items, [{"id": 2}, {"id": 3}])
items = utils.parse_to_list_of_dicts([[{"id": 4}]])
self.assertEqual(items, [{"id": 4}])
items = utils.parse_to_list_of_dicts(
[[{"id": 5}, {"id": 6}], {"id": 7}])
self.assertEqual(items, [{"id": 5}, {"id": 6}, {"id": 7}])
self.assertRaisesRegexp(
TypeError, 'A dict or list instance expected',
utils.parse_to_list_of_dicts, [42])

View File

@ -161,6 +161,30 @@ node-4 ansible_host=10.20.0.5
self.m_get_client.assert_called_once_with('node', mock.ANY)
self.m_client.node_vms_create.assert_called_once_with(node_id, config)
def test_node_vms_conf_create_from_list(self):
vms_conf = '[{"id": 2}, {"id": 3}]'
config = [{'id': 2}, {'id': 3}]
node_id = 42
args = "node create-vms-conf {0} --conf '{1}'".format(
node_id, vms_conf)
self.exec_command(args)
self.m_get_client.assert_called_once_with('node', mock.ANY)
self.m_client.node_vms_create.assert_called_once_with(node_id, config)
@mock.patch('argparse.ArgumentParser.error')
def test_node_vms_conf_create_fail(self, m_error):
vms_conf = '[{"id": '
node_id = 42
args = "node create-vms-conf {0} --conf '{1}'".format(
node_id, vms_conf)
self.exec_command(args)
args, _ = m_error.call_args
self.assertIn('--conf', args[0])
def test_node_set_hostname(self):
self.m_client._updatable_attributes = \
node.NodeClient._updatable_attributes

View File

@ -17,7 +17,6 @@
import functools
import glob
import io
import json
import os
import six
import subprocess
@ -135,7 +134,7 @@ def file_exists(path):
return os.path.lexists(path)
def parse_to_list_of_dicts(str_list):
def parse_to_list_of_dicts(items):
"""Parse list of json strings to dictionaries
:param list: list of dicts and json string
@ -143,14 +142,14 @@ def parse_to_list_of_dicts(str_list):
"""
dict_list = []
for json_str in str_list:
if not isinstance(json_str, dict):
try:
json_str = json.loads(json_str)
except Exception:
raise error.BadDataException(
'Not valid JSON data: {0}'.format(json_str))
dict_list.append(json_str)
for item in items:
if isinstance(item, dict):
dict_list.append(item)
elif isinstance(item, list):
dict_list.extend(item)
else:
raise TypeError(
'A dict or list instance expected: {0}'.format(item))
return dict_list