diff --git a/ironicclient/common/cliutils.py b/ironicclient/common/cliutils.py index d1cbc1643..9936e64c5 100644 --- a/ironicclient/common/cliutils.py +++ b/ironicclient/common/cliutils.py @@ -140,7 +140,7 @@ def isunauthenticated(func): def print_list(objs, fields, formatters=None, sortby_index=0, mixed_case_fields=None, field_labels=None): - """Print a list of objects as a table, one row per object. + """Print a list of objects or dict as a table, one row per object or dict. :param objs: iterable of :class:`Resource` :param fields: attributes that correspond to columns, in order @@ -176,7 +176,10 @@ def print_list(objs, fields, formatters=None, sortby_index=0, field_name = field.replace(' ', '_') else: field_name = field.lower().replace(' ', '_') - data = getattr(o, field_name, '') + if isinstance(o, dict): + data = o.get(field_name, '') + else: + data = getattr(o, field_name, '') row.append(data) pt.add_row(row) diff --git a/ironicclient/tests/unit/test_cliutils.py b/ironicclient/tests/unit/test_cliutils.py index 02c76da50..24341f8c7 100644 --- a/ironicclient/tests/unit/test_cliutils.py +++ b/ironicclient/tests/unit/test_cliutils.py @@ -499,6 +499,17 @@ class PrintResultTestCase(test_base.BaseTestCase): self.mock_get_string.assert_called_with() self.mock_init.assert_called_once_with(["Name", "Value"]) + def test_print_list_dict(self): + objs = [{'name': 'k1', 'value': 1}, + {'name': 'k2', 'value': 2}] + cliutils.print_list(objs, ["Name", "Value"], sortby_index=None) + + self.assertEqual(self.mock_add_row.call_args_list, + [mock.call(["k1", 1]), + mock.call(["k2", 2])]) + self.mock_get_string.assert_called_with() + self.mock_init.assert_called_once_with(["Name", "Value"]) + def test_print_dict(self): cliutils.print_dict({"K": "k", "Key": "Value"}) cliutils.print_dict({"K": "k", "Key": "Long\\nValue"})