diff --git a/ironicclient/common/utils.py b/ironicclient/common/utils.py index 32db2b870..18f97b1e2 100644 --- a/ironicclient/common/utils.py +++ b/ironicclient/common/utils.py @@ -25,6 +25,7 @@ import sys import tempfile import time +from cliff import columns from oslo_utils import strutils import yaml @@ -458,3 +459,26 @@ def get_json_data(data): return json.loads(data) except ValueError: return None + + +def format_hash(data): + if data is None: + return None + + output = "" + for s in sorted(data): + key_str = s + if isinstance(data[s], dict): + # NOTE(dtroyer): Only append the separator chars here, quoting + # is completely handled in the terminal case. + output = output + format_hash(data[s], prefix=key_str) + ", " + elif data[s] is not None: + output = output + key_str + "='" + str(data[s]) + "', " + else: + output = output + key_str + "=, " + return output[:-2] + + +class HashColumn(columns.FormattableColumn): + def human_readable(self): + return format_hash(self._value) diff --git a/ironicclient/osc/v1/baremetal_chassis.py b/ironicclient/osc/v1/baremetal_chassis.py index a84fc52f4..58dc5bb61 100644 --- a/ironicclient/osc/v1/baremetal_chassis.py +++ b/ironicclient/osc/v1/baremetal_chassis.py @@ -190,7 +190,7 @@ class ListBaremetalChassis(command.Lister): return (labels, (oscutils.get_item_properties(s, columns, formatters={ - 'Properties': oscutils.format_dict},) for s in data)) + 'Properties': utils.HashColumn},) for s in data)) class SetBaremetalChassis(command.Command): diff --git a/ironicclient/osc/v1/baremetal_conductor.py b/ironicclient/osc/v1/baremetal_conductor.py index 627fd6227..2dbb9c8c5 100755 --- a/ironicclient/osc/v1/baremetal_conductor.py +++ b/ironicclient/osc/v1/baremetal_conductor.py @@ -21,6 +21,7 @@ from osc_lib.command import command from osc_lib import utils as oscutils from ironicclient.common.i18n import _ +from ironicclient.common import utils from ironicclient import exc from ironicclient.v1 import resource_fields as res_fields @@ -106,7 +107,7 @@ class ListBaremetalConductor(command.Lister): return (labels, (oscutils.get_item_properties(s, columns, formatters={ - 'Properties': oscutils.format_dict},) for s in data)) + 'Properties': utils.HashColumn},) for s in data)) class ShowBaremetalConductor(command.ShowOne): diff --git a/ironicclient/osc/v1/baremetal_node.py b/ironicclient/osc/v1/baremetal_node.py index 3257fc049..3422460a6 100755 --- a/ironicclient/osc/v1/baremetal_node.py +++ b/ironicclient/osc/v1/baremetal_node.py @@ -860,7 +860,7 @@ class ListBaremetalNode(command.Lister): return (labels, (oscutils.get_item_properties(s, columns, formatters={ - 'Properties': oscutils.format_dict},) for s in data)) + 'Properties': utils.HashColumn},) for s in data)) class MaintenanceSetBaremetalNode(command.Command): diff --git a/ironicclient/osc/v1/baremetal_port.py b/ironicclient/osc/v1/baremetal_port.py index ceb670230..dbbfe5afa 100644 --- a/ironicclient/osc/v1/baremetal_port.py +++ b/ironicclient/osc/v1/baremetal_port.py @@ -523,4 +523,4 @@ class ListBaremetalPort(command.Lister): return (labels, (oscutils.get_item_properties(s, columns, formatters={ - 'extra': oscutils.format_dict},) for s in data)) + 'extra': utils.HashColumn},) for s in data)) diff --git a/ironicclient/osc/v1/baremetal_portgroup.py b/ironicclient/osc/v1/baremetal_portgroup.py index bd7f1a2be..a1dc40486 100644 --- a/ironicclient/osc/v1/baremetal_portgroup.py +++ b/ironicclient/osc/v1/baremetal_portgroup.py @@ -252,7 +252,7 @@ class ListBaremetalPortGroup(command.Lister): return (labels, (oscutils.get_item_properties(s, columns, formatters={ - 'Properties': oscutils.format_dict},) for s in data)) + 'Properties': utils.HashColumn},) for s in data)) class DeleteBaremetalPortGroup(command.Command): diff --git a/ironicclient/osc/v1/baremetal_volume_connector.py b/ironicclient/osc/v1/baremetal_volume_connector.py index f8b270ad1..cb2e9cd4b 100644 --- a/ironicclient/osc/v1/baremetal_volume_connector.py +++ b/ironicclient/osc/v1/baremetal_volume_connector.py @@ -218,7 +218,7 @@ class ListBaremetalVolumeConnector(command.Lister): return (labels, (oscutils.get_item_properties(s, columns, formatters={ - 'Properties': oscutils.format_dict},) for s in data)) + 'Properties': utils.HashColumn},) for s in data)) class DeleteBaremetalVolumeConnector(command.Command): diff --git a/ironicclient/osc/v1/baremetal_volume_target.py b/ironicclient/osc/v1/baremetal_volume_target.py index 7940e482c..614781aae 100644 --- a/ironicclient/osc/v1/baremetal_volume_target.py +++ b/ironicclient/osc/v1/baremetal_volume_target.py @@ -234,7 +234,7 @@ class ListBaremetalVolumeTarget(command.Lister): return (labels, (oscutils.get_item_properties(s, columns, formatters={ - 'Properties': oscutils.format_dict},) for s in data)) + 'Properties': utils.HashColumn},) for s in data)) class DeleteBaremetalVolumeTarget(command.Command): diff --git a/ironicclient/tests/unit/osc/v1/test_baremetal_port.py b/ironicclient/tests/unit/osc/v1/test_baremetal_port.py index 2b8fde49a..482e7e28c 100644 --- a/ironicclient/tests/unit/osc/v1/test_baremetal_port.py +++ b/ironicclient/tests/unit/osc/v1/test_baremetal_port.py @@ -18,8 +18,8 @@ import copy from unittest import mock from osc_lib.tests import utils as osctestutils -from osc_lib import utils as oscutils +from ironicclient.common import utils from ironicclient import exc from ironicclient.osc.v1 import baremetal_port from ironicclient.tests.unit.osc.v1 import fakes as baremetal_fakes @@ -757,7 +757,7 @@ class TestBaremetalPortList(TestBaremetalPort): baremetal_fakes.baremetal_port_uuid, baremetal_fakes.baremetal_port_address, '', - oscutils.format_dict(baremetal_fakes.baremetal_port_extra), + utils.HashColumn(baremetal_fakes.baremetal_port_extra), baremetal_fakes.baremetal_uuid, '', '', diff --git a/ironicclient/tests/unit/v1/test_node.py b/ironicclient/tests/unit/v1/test_node.py index 8356dfa88..c1ee1cec3 100644 --- a/ironicclient/tests/unit/v1/test_node.py +++ b/ironicclient/tests/unit/v1/test_node.py @@ -2197,7 +2197,7 @@ class NodeManagerTest(testtools.TestCase): mock_get.side_effect = side_effect self.assertRaisesRegex(exc.StateTransitionTimeout, - r'Node\(s\) node2', + r'.*node2.*', self.mgr.wait_for_provision_state, ['node1', 'node2'], 'active', timeout=0.001)