summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/network/v2/security_group_rule.py12
-rw-r--r--openstackclient/object/v1/account.py5
-rw-r--r--openstackclient/object/v1/container.py3
-rw-r--r--openstackclient/object/v1/object.py3
-rw-r--r--openstackclient/tests/functional/volume/v1/test_qos.py4
-rw-r--r--openstackclient/tests/functional/volume/v1/test_snapshot.py9
-rw-r--r--openstackclient/tests/functional/volume/v1/test_volume.py6
-rw-r--r--openstackclient/tests/functional/volume/v1/test_volume_type.py61
-rw-r--r--openstackclient/tests/functional/volume/v2/test_qos.py6
-rw-r--r--openstackclient/tests/functional/volume/v2/test_volume.py6
-rw-r--r--openstackclient/tests/functional/volume/v2/test_volume_snapshot.py8
-rw-r--r--openstackclient/tests/functional/volume/v2/test_volume_type.py74
-rw-r--r--openstackclient/tests/unit/network/v2/fakes.py2
-rw-r--r--openstackclient/tests/unit/network/v2/test_security_group_rule_network.py4
-rw-r--r--openstackclient/tests/unit/volume/v1/test_qos_specs.py28
-rw-r--r--openstackclient/tests/unit/volume/v1/test_type.py59
-rw-r--r--openstackclient/tests/unit/volume/v1/test_volume.py79
-rw-r--r--openstackclient/tests/unit/volume/v1/test_volume_backup.py12
-rw-r--r--openstackclient/tests/unit/volume/v2/fakes.py5
-rw-r--r--openstackclient/tests/unit/volume/v2/test_consistency_group.py17
-rw-r--r--openstackclient/tests/unit/volume/v2/test_qos_specs.py28
-rw-r--r--openstackclient/tests/unit/volume/v2/test_type.py75
-rw-r--r--openstackclient/tests/unit/volume/v2/test_volume.py126
-rw-r--r--openstackclient/tests/unit/volume/v2/test_volume_backup.py6
-rw-r--r--openstackclient/volume/v1/qos_specs.py13
-rw-r--r--openstackclient/volume/v1/volume.py62
-rw-r--r--openstackclient/volume/v1/volume_backup.py45
-rw-r--r--openstackclient/volume/v1/volume_snapshot.py54
-rw-r--r--openstackclient/volume/v1/volume_type.py60
-rw-r--r--openstackclient/volume/v2/consistency_group.py3
-rw-r--r--openstackclient/volume/v2/qos_specs.py13
-rw-r--r--openstackclient/volume/v2/volume.py62
-rw-r--r--openstackclient/volume/v2/volume_backup.py45
-rw-r--r--openstackclient/volume/v2/volume_snapshot.py54
-rw-r--r--openstackclient/volume/v2/volume_type.py61
35 files changed, 701 insertions, 409 deletions
diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py
index df19af20..637fba1d 100644
--- a/openstackclient/network/v2/security_group_rule.py
+++ b/openstackclient/network/v2/security_group_rule.py
@@ -155,7 +155,7 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
"ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, "
"ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, "
"udp, udplite, vrrp and integer representations [0-255] "
- "or any; default: tcp)")
+ "or any; default: any (all protocols))")
)
protocol_group.add_argument(
'--proto',
@@ -220,8 +220,8 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
)
return parser
- def _get_protocol(self, parsed_args):
- protocol = 'tcp'
+ def _get_protocol(self, parsed_args, default_protocol='any'):
+ protocol = default_protocol
if parsed_args.protocol is not None:
protocol = parsed_args.protocol
if parsed_args.proto is not None:
@@ -324,7 +324,7 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
def take_action_compute(self, client, parsed_args):
group = client.api.security_group_find(parsed_args.group)
- protocol = self._get_protocol(parsed_args)
+ protocol = self._get_protocol(parsed_args, default_protocol='tcp')
if protocol == 'icmp':
from_port, to_port = -1, -1
else:
@@ -415,8 +415,8 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
"ah, dhcp, egp, esp, gre, icmp, igmp, "
"ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, "
"ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, "
- "udp, udplite, vrrp and integer representations [0-255])."
- )
+ "udp, udplite, vrrp and integer representations [0-255] "
+ "or any; default: any (all protocols))")
)
direction_group = parser.add_mutually_exclusive_group()
direction_group.add_argument(
diff --git a/openstackclient/object/v1/account.py b/openstackclient/object/v1/account.py
index 4847f8bb..95be8132 100644
--- a/openstackclient/object/v1/account.py
+++ b/openstackclient/object/v1/account.py
@@ -13,9 +13,9 @@
"""Account v1 action implementations"""
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
-from osc_lib import utils
import six
from openstackclient.i18n import _
@@ -48,7 +48,8 @@ class ShowAccount(command.ShowOne):
def take_action(self, parsed_args):
data = self.app.client_manager.object_store.account_show()
if 'properties' in data:
- data['properties'] = utils.format_dict(data.pop('properties'))
+ data['properties'] = format_columns.DictColumn(
+ data.pop('properties'))
return zip(*sorted(six.iteritems(data)))
diff --git a/openstackclient/object/v1/container.py b/openstackclient/object/v1/container.py
index 9f689ab6..02e8d277 100644
--- a/openstackclient/object/v1/container.py
+++ b/openstackclient/object/v1/container.py
@@ -17,6 +17,7 @@
import logging
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import utils
@@ -230,7 +231,7 @@ class ShowContainer(command.ShowOne):
container=parsed_args.container,
)
if 'properties' in data:
- data['properties'] = utils.format_dict(data.pop('properties'))
+ data['properties'] = format_columns.DictColumn(data['properties'])
return zip(*sorted(six.iteritems(data)))
diff --git a/openstackclient/object/v1/object.py b/openstackclient/object/v1/object.py
index aeb02536..3747e19e 100644
--- a/openstackclient/object/v1/object.py
+++ b/openstackclient/object/v1/object.py
@@ -17,6 +17,7 @@
import logging
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -284,7 +285,7 @@ class ShowObject(command.ShowOne):
object=parsed_args.object,
)
if 'properties' in data:
- data['properties'] = utils.format_dict(data.pop('properties'))
+ data['properties'] = format_columns.DictColumn(data['properties'])
return zip(*sorted(six.iteritems(data)))
diff --git a/openstackclient/tests/functional/volume/v1/test_qos.py b/openstackclient/tests/functional/volume/v1/test_qos.py
index 434840f6..d8277dfc 100644
--- a/openstackclient/tests/functional/volume/v1/test_qos.py
+++ b/openstackclient/tests/functional/volume/v1/test_qos.py
@@ -93,7 +93,7 @@ class QosTests(common.BaseVolumeTests):
cmd_output['name']
)
self.assertEqual(
- "Alpha='c', Beta='b'",
+ {'Alpha': 'c', 'Beta': 'b'},
cmd_output['properties']
)
@@ -114,7 +114,7 @@ class QosTests(common.BaseVolumeTests):
cmd_output['name']
)
self.assertEqual(
- "Beta='b'",
+ {'Beta': 'b'},
cmd_output['properties']
)
diff --git a/openstackclient/tests/functional/volume/v1/test_snapshot.py b/openstackclient/tests/functional/volume/v1/test_snapshot.py
index 083cd1b0..5a76a2e9 100644
--- a/openstackclient/tests/functional/volume/v1/test_snapshot.py
+++ b/openstackclient/tests/functional/volume/v1/test_snapshot.py
@@ -204,7 +204,7 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
cmd_output["display_description"],
)
self.assertEqual(
- "Alpha='a', Beta='b'",
+ {'Alpha': 'a', 'Beta': 'b'},
cmd_output["properties"],
)
@@ -221,7 +221,7 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
new_name
))
self.assertEqual(
- "Beta='b'",
+ {'Beta': 'b'},
cmd_output["properties"],
)
@@ -236,7 +236,4 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
'volume snapshot show -f json ' +
new_name
))
- self.assertNotIn(
- "Beta='b'",
- cmd_output["properties"],
- )
+ self.assertEqual({}, cmd_output["properties"])
diff --git a/openstackclient/tests/functional/volume/v1/test_volume.py b/openstackclient/tests/functional/volume/v1/test_volume.py
index 001bbe6e..013bc6a4 100644
--- a/openstackclient/tests/functional/volume/v1/test_volume.py
+++ b/openstackclient/tests/functional/volume/v1/test_volume.py
@@ -123,7 +123,7 @@ class VolumeTests(common.BaseVolumeTests):
cmd_output["display_description"],
)
self.assertEqual(
- "Alpha='a'",
+ {'Alpha': 'a'},
cmd_output["properties"],
)
self.assertEqual(
@@ -165,7 +165,7 @@ class VolumeTests(common.BaseVolumeTests):
cmd_output["display_description"],
)
self.assertEqual(
- "Beta='b', Gamma='c'",
+ {'Beta': 'b', 'Gamma': 'c'},
cmd_output["properties"],
)
self.assertEqual(
@@ -186,7 +186,7 @@ class VolumeTests(common.BaseVolumeTests):
new_name
))
self.assertEqual(
- "Gamma='c'",
+ {'Gamma': 'c'},
cmd_output["properties"],
)
diff --git a/openstackclient/tests/functional/volume/v1/test_volume_type.py b/openstackclient/tests/functional/volume/v1/test_volume_type.py
index eb9d7f64..fb8dabdb 100644
--- a/openstackclient/tests/functional/volume/v1/test_volume_type.py
+++ b/openstackclient/tests/functional/volume/v1/test_volume_type.py
@@ -66,8 +66,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json %s' % name
))
- # TODO(amotoki): properties output should be machine-readable
- self.assertEqual("a='b', c='d'", cmd_output['properties'])
+ self.assertEqual({'a': 'b', 'c': 'd'}, cmd_output['properties'])
raw_output = self.openstack(
'volume type unset --property a %s' % name
@@ -76,7 +75,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json %s' % name
))
- self.assertEqual("c='d'", cmd_output['properties'])
+ self.assertEqual({'c': 'd'}, cmd_output['properties'])
def test_volume_type_set_unset_multiple_properties(self):
name = uuid.uuid4().hex
@@ -97,7 +96,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json %s' % name
))
- self.assertEqual("a='b', c='d'", cmd_output['properties'])
+ self.assertEqual({'a': 'b', 'c': 'd'}, cmd_output['properties'])
raw_output = self.openstack(
'volume type unset --property a --property c %s' % name
@@ -106,7 +105,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json %s' % name
))
- self.assertEqual("", cmd_output['properties'])
+ self.assertEqual({}, cmd_output['properties'])
def test_multi_delete(self):
vol_type1 = uuid.uuid4().hex
@@ -133,34 +132,32 @@ class VolumeTypeTests(common.BaseVolumeTests):
'--encryption-key-size 128 '
'--encryption-control-location front-end ' +
encryption_type))
- # TODO(amotoki): encryption output should be machine-readable
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='128'",
- "control_location='front-end'"]
- for attr in expected:
- self.assertIn(attr, cmd_output['encryption'])
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 128,
+ 'control_location': 'front-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, cmd_output['encryption'][attr])
# test show encryption type
cmd_output = json.loads(self.openstack(
'volume type show -f json --encryption-type ' + encryption_type))
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='128'",
- "control_location='front-end'"]
- for attr in expected:
- self.assertIn(attr, cmd_output['encryption'])
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 128,
+ 'control_location': 'front-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, cmd_output['encryption'][attr])
# test list encryption type
cmd_output = json.loads(self.openstack(
'volume type list -f json --encryption-type'))
encryption_output = [t['Encryption'] for t in cmd_output
if t['Name'] == encryption_type][0]
- # TODO(amotoki): encryption output should be machine-readable
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='128'",
- "control_location='front-end'"]
- for attr in expected:
- self.assertIn(attr, encryption_output)
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 128,
+ 'control_location': 'front-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, encryption_output[attr])
# test set new encryption type
raw_output = self.openstack(
'volume type set '
@@ -185,12 +182,12 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json --encryption-type ' + name
))
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='128'",
- "control_location='front-end'"]
- for attr in expected:
- self.assertIn(attr, cmd_output['encryption'])
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 128,
+ 'control_location': 'front-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, cmd_output['encryption'][attr])
# test unset encryption type
raw_output = self.openstack(
'volume type unset --encryption-type ' + name
@@ -199,7 +196,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json --encryption-type ' + name
))
- self.assertEqual('', cmd_output['encryption'])
+ self.assertEqual({}, cmd_output['encryption'])
# test delete encryption type
raw_output = self.openstack('volume type delete ' + encryption_type)
self.assertEqual('', raw_output)
diff --git a/openstackclient/tests/functional/volume/v2/test_qos.py b/openstackclient/tests/functional/volume/v2/test_qos.py
index 646becc1..f9f6e099 100644
--- a/openstackclient/tests/functional/volume/v2/test_qos.py
+++ b/openstackclient/tests/functional/volume/v2/test_qos.py
@@ -74,7 +74,7 @@ class QosTests(common.BaseVolumeTests):
cmd_output['consumer']
)
self.assertEqual(
- "Alpha='a'",
+ {'Alpha': 'a'},
cmd_output['properties']
)
@@ -97,7 +97,7 @@ class QosTests(common.BaseVolumeTests):
cmd_output['name']
)
self.assertEqual(
- "Alpha='c', Beta='b'",
+ {'Alpha': 'c', 'Beta': 'b'},
cmd_output['properties']
)
@@ -118,7 +118,7 @@ class QosTests(common.BaseVolumeTests):
cmd_output['name']
)
self.assertEqual(
- "Beta='b'",
+ {'Beta': 'b'},
cmd_output['properties']
)
diff --git a/openstackclient/tests/functional/volume/v2/test_volume.py b/openstackclient/tests/functional/volume/v2/test_volume.py
index 2930d483..19fd5895 100644
--- a/openstackclient/tests/functional/volume/v2/test_volume.py
+++ b/openstackclient/tests/functional/volume/v2/test_volume.py
@@ -128,7 +128,7 @@ class VolumeTests(common.BaseVolumeTests):
cmd_output["description"],
)
self.assertEqual(
- "Alpha='a'",
+ {'Alpha': 'a'},
cmd_output["properties"],
)
self.assertEqual(
@@ -170,7 +170,7 @@ class VolumeTests(common.BaseVolumeTests):
cmd_output["description"],
)
self.assertEqual(
- "Beta='b', Gamma='c'",
+ {'Beta': 'b', 'Gamma': 'c'},
cmd_output["properties"],
)
self.assertEqual(
@@ -196,7 +196,7 @@ class VolumeTests(common.BaseVolumeTests):
new_name
))
self.assertEqual(
- "Gamma='c'",
+ {'Gamma': 'c'},
cmd_output["properties"],
)
self.assertEqual(
diff --git a/openstackclient/tests/functional/volume/v2/test_volume_snapshot.py b/openstackclient/tests/functional/volume/v2/test_volume_snapshot.py
index 264f4adb..8d32d997 100644
--- a/openstackclient/tests/functional/volume/v2/test_volume_snapshot.py
+++ b/openstackclient/tests/functional/volume/v2/test_volume_snapshot.py
@@ -182,7 +182,7 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
cmd_output["description"],
)
self.assertEqual(
- "Alpha='a'",
+ {'Alpha': 'a'},
cmd_output["properties"],
)
self.wait_for_status('volume snapshot', name, 'available')
@@ -216,7 +216,7 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
cmd_output["description"],
)
self.assertEqual(
- "Alpha='c', Beta='b'",
+ {'Alpha': 'c', 'Beta': 'b'},
cmd_output["properties"],
)
@@ -233,7 +233,7 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
new_name
))
self.assertEqual(
- "Beta='b'",
+ {'Beta': 'b'},
cmd_output["properties"],
)
@@ -249,6 +249,6 @@ class VolumeSnapshotTests(common.BaseVolumeTests):
new_name
))
self.assertNotIn(
- "Beta='b'",
+ {'Beta': 'b'},
cmd_output["properties"],
)
diff --git a/openstackclient/tests/functional/volume/v2/test_volume_type.py b/openstackclient/tests/functional/volume/v2/test_volume_type.py
index d8dd5bd6..3f1a6ea8 100644
--- a/openstackclient/tests/functional/volume/v2/test_volume_type.py
+++ b/openstackclient/tests/functional/volume/v2/test_volume_type.py
@@ -65,8 +65,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json %s' % name
))
- # TODO(amotoki): properties output should be machine-readable
- self.assertEqual("a='b', c='d'", cmd_output['properties'])
+ self.assertEqual({'a': 'b', 'c': 'd'}, cmd_output['properties'])
raw_output = self.openstack(
'volume type unset --property a %s' % name
@@ -75,7 +74,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json %s' % name
))
- self.assertEqual("c='d'", cmd_output['properties'])
+ self.assertEqual({'c': 'd'}, cmd_output['properties'])
def test_volume_type_set_unset_multiple_properties(self):
name = uuid.uuid4().hex
@@ -96,7 +95,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json %s' % name
))
- self.assertEqual("a='b', c='d'", cmd_output['properties'])
+ self.assertEqual({'a': 'b', 'c': 'd'}, cmd_output['properties'])
raw_output = self.openstack(
'volume type unset --property a --property c %s' % name
@@ -105,7 +104,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json %s' % name
))
- self.assertEqual("", cmd_output['properties'])
+ self.assertEqual({}, cmd_output['properties'])
def test_volume_type_set_unset_project(self):
name = uuid.uuid4().hex
@@ -155,35 +154,32 @@ class VolumeTypeTests(common.BaseVolumeTests):
'--encryption-key-size 128 '
'--encryption-control-location front-end ' +
encryption_type))
- # TODO(amotoki): encryption output should be machine-readable
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='128'",
- "control_location='front-end'"]
- for attr in expected:
- self.assertIn(attr, cmd_output['encryption'])
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 128,
+ 'control_location': 'front-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, cmd_output['encryption'][attr])
# test show encryption type
cmd_output = json.loads(self.openstack(
'volume type show -f json --encryption-type ' + encryption_type))
- # TODO(amotoki): encryption output should be machine-readable
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='128'",
- "control_location='front-end'"]
- for attr in expected:
- self.assertIn(attr, cmd_output['encryption'])
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 128,
+ 'control_location': 'front-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, cmd_output['encryption'][attr])
# test list encryption type
cmd_output = json.loads(self.openstack(
'volume type list -f json --encryption-type'))
encryption_output = [t['Encryption'] for t in cmd_output
if t['Name'] == encryption_type][0]
- # TODO(amotoki): encryption output should be machine-readable
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='128'",
- "control_location='front-end'"]
- for attr in expected:
- self.assertIn(attr, encryption_output)
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 128,
+ 'control_location': 'front-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, encryption_output[attr])
# test set existing encryption type
raw_output = self.openstack(
'volume type set '
@@ -193,12 +189,12 @@ class VolumeTypeTests(common.BaseVolumeTests):
self.assertEqual('', raw_output)
cmd_output = json.loads(self.openstack(
'volume type show -f json --encryption-type ' + encryption_type))
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='256'",
- "control_location='back-end'"]
- for attr in expected:
- self.assertIn(attr, cmd_output['encryption'])
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 256,
+ 'control_location': 'back-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, cmd_output['encryption'][attr])
# test set new encryption type
cmd_output = json.loads(self.openstack(
'volume type create -f json --private ' +
@@ -222,12 +218,12 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json --encryption-type ' + name
))
- expected = ["provider='LuksEncryptor'",
- "cipher='aes-xts-plain64'",
- "key_size='128'",
- "control_location='front-end'"]
- for attr in expected:
- self.assertIn(attr, cmd_output['encryption'])
+ expected = {'provider': 'LuksEncryptor',
+ 'cipher': 'aes-xts-plain64',
+ 'key_size': 128,
+ 'control_location': 'front-end'}
+ for attr, value in expected.items():
+ self.assertEqual(value, cmd_output['encryption'][attr])
# test unset encryption type
raw_output = self.openstack(
'volume type unset --encryption-type ' + name
@@ -236,7 +232,7 @@ class VolumeTypeTests(common.BaseVolumeTests):
cmd_output = json.loads(self.openstack(
'volume type show -f json --encryption-type ' + name
))
- self.assertEqual('', cmd_output['encryption'])
+ self.assertEqual({}, cmd_output['encryption'])
# test delete encryption type
raw_output = self.openstack('volume type delete ' + encryption_type)
self.assertEqual('', raw_output)
diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py
index 100ea2b1..e41621a4 100644
--- a/openstackclient/tests/unit/network/v2/fakes.py
+++ b/openstackclient/tests/unit/network/v2/fakes.py
@@ -1305,7 +1305,7 @@ class FakeSecurityGroupRule(object):
'id': 'security-group-rule-id-' + uuid.uuid4().hex,
'port_range_max': None,
'port_range_min': None,
- 'protocol': 'tcp',
+ 'protocol': None,
'remote_group_id': None,
'remote_ip_prefix': '0.0.0.0/0',
'security_group_id': 'security-group-id-' + uuid.uuid4().hex,
diff --git a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py
index 2b0de0d2..eb0cf310 100644
--- a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py
+++ b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py
@@ -168,10 +168,12 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
def test_create_default_rule(self):
self._setup_security_group_rule({
+ 'protocol': 'tcp',
'port_range_max': 443,
'port_range_min': 443,
})
arglist = [
+ '--protocol', 'tcp',
'--dst-port', str(self._security_group_rule.port_range_min),
self._security_group.id,
]
@@ -258,10 +260,12 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
def test_create_remote_group(self):
self._setup_security_group_rule({
+ 'protocol': 'tcp',
'port_range_max': 22,
'port_range_min': 22,
})
arglist = [
+ '--protocol', 'tcp',
'--dst-port', str(self._security_group_rule.port_range_min),
'--ingress',
'--remote-group', self._security_group.name,
diff --git a/openstackclient/tests/unit/volume/v1/test_qos_specs.py b/openstackclient/tests/unit/volume/v1/test_qos_specs.py
index 442840f9..11dc8084 100644
--- a/openstackclient/tests/unit/volume/v1/test_qos_specs.py
+++ b/openstackclient/tests/unit/volume/v1/test_qos_specs.py
@@ -17,6 +17,8 @@ import copy
import mock
from mock import call
+
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -85,7 +87,7 @@ class TestQosCreate(TestQos):
self.new_qos_spec.consumer,
self.new_qos_spec.id,
self.new_qos_spec.name,
- utils.format_dict(self.new_qos_spec.specs)
+ format_columns.DictColumn(self.new_qos_spec.specs)
)
self.qos_mock.create.return_value = self.new_qos_spec
# Get the command object to test
@@ -108,7 +110,7 @@ class TestQosCreate(TestQos):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_qos_create_with_consumer(self):
arglist = [
@@ -128,7 +130,7 @@ class TestQosCreate(TestQos):
{'consumer': self.new_qos_spec.consumer}
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_qos_create_with_properties(self):
arglist = [
@@ -154,7 +156,7 @@ class TestQosCreate(TestQos):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
class TestQosDelete(TestQos):
@@ -326,8 +328,8 @@ class TestQosList(TestQos):
q.id,
q.name,
q.consumer,
- qos_association.name,
- utils.format_dict(q.specs),
+ format_columns.ListColumn([qos_association.name]),
+ format_columns.DictColumn(q.specs),
))
def setUp(self):
@@ -349,7 +351,7 @@ class TestQosList(TestQos):
self.qos_mock.list.assert_called_with()
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_qos_list_no_association(self):
self.qos_mock.reset_mock()
@@ -373,10 +375,10 @@ class TestQosList(TestQos):
self.qos_specs[1].id,
self.qos_specs[1].name,
self.qos_specs[1].consumer,
- None,
- utils.format_dict(self.qos_specs[1].specs),
+ format_columns.ListColumn(None),
+ format_columns.DictColumn(self.qos_specs[1].specs),
)
- self.assertEqual(ex_data, list(data))
+ self.assertListItemEqual(ex_data, list(data))
class TestQosSet(TestQos):
@@ -447,13 +449,13 @@ class TestQosShow(TestQos):
)
self.assertEqual(collist, columns)
datalist = (
- self.qos_association.name,
+ format_columns.ListColumn([self.qos_association.name]),
self.qos_spec.consumer,
self.qos_spec.id,
self.qos_spec.name,
- utils.format_dict(self.qos_spec.specs),
+ format_columns.DictColumn(self.qos_spec.specs),
)
- self.assertEqual(datalist, tuple(data))
+ self.assertItemEqual(datalist, tuple(data))
class TestQosUnset(TestQos):
diff --git a/openstackclient/tests/unit/volume/v1/test_type.py b/openstackclient/tests/unit/volume/v1/test_type.py
index dcdd3d56..beff8336 100644
--- a/openstackclient/tests/unit/volume/v1/test_type.py
+++ b/openstackclient/tests/unit/volume/v1/test_type.py
@@ -15,6 +15,7 @@
import mock
from mock import call
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -77,7 +78,7 @@ class TestTypeCreate(TestType):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_type_create_with_encryption(self):
encryption_info = {
@@ -102,7 +103,7 @@ class TestTypeCreate(TestType):
)
encryption_data = (
self.new_volume_type.description,
- utils.format_dict(encryption_info),
+ format_columns.DictColumn(encryption_info),
self.new_volume_type.id,
True,
self.new_volume_type.name,
@@ -138,7 +139,7 @@ class TestTypeCreate(TestType):
body,
)
self.assertEqual(encryption_columns, columns)
- self.assertEqual(encryption_data, data)
+ self.assertItemEqual(encryption_data, data)
class TestTypeDelete(TestType):
@@ -246,7 +247,7 @@ class TestTypeList(TestType):
t.id,
t.name,
t.is_public,
- utils.format_dict(t.extra_specs),
+ format_columns.DictColumn(t.extra_specs),
))
def setUp(self):
@@ -269,7 +270,7 @@ class TestTypeList(TestType):
columns, data = self.cmd.take_action(parsed_args)
self.types_mock.list.assert_called_once_with()
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_type_list_with_options(self):
arglist = [
@@ -283,7 +284,7 @@ class TestTypeList(TestType):
columns, data = self.cmd.take_action(parsed_args)
self.types_mock.list.assert_called_once_with()
self.assertEqual(self.columns_long, columns)
- self.assertEqual(self.data_long, list(data))
+ self.assertListItemEqual(self.data_long, list(data))
def test_type_list_with_encryption(self):
encryption_type = volume_fakes.FakeType.create_one_encryption_type(
@@ -302,13 +303,16 @@ class TestTypeList(TestType):
self.volume_types[0].id,
self.volume_types[0].name,
self.volume_types[0].is_public,
- utils.format_dict(encryption_info),
+ volume_type.EncryptionInfoColumn(
+ self.volume_types[0].id,
+ {self.volume_types[0].id: encryption_info}),
))
encryption_data.append((
self.volume_types[1].id,
self.volume_types[1].name,
self.volume_types[1].is_public,
- '-',
+ volume_type.EncryptionInfoColumn(
+ self.volume_types[1].id, {}),
))
self.encryption_types_mock.list.return_value = [encryption_type]
@@ -324,7 +328,7 @@ class TestTypeList(TestType):
self.encryption_types_mock.list.assert_called_once_with()
self.types_mock.list.assert_called_once_with()
self.assertEqual(encryption_columns, columns)
- self.assertEqual(encryption_data, list(data))
+ self.assertListItemEqual(encryption_data, list(data))
class TestTypeSet(TestType):
@@ -443,7 +447,7 @@ class TestTypeShow(TestType):
self.volume_type.id,
True,
self.volume_type.name,
- utils.format_dict(self.volume_type.extra_specs)
+ format_columns.DictColumn(self.volume_type.extra_specs)
)
self.types_mock.get.return_value = self.volume_type
@@ -465,7 +469,7 @@ class TestTypeShow(TestType):
self.types_mock.get.assert_called_with(self.volume_type.id)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_type_show_with_encryption(self):
encryption_type = volume_fakes.FakeType.create_one_encryption_type()
@@ -489,11 +493,11 @@ class TestTypeShow(TestType):
)
encryption_data = (
self.volume_type.description,
- utils.format_dict(encryption_info),
+ format_columns.DictColumn(encryption_info),
self.volume_type.id,
True,
self.volume_type.name,
- utils.format_dict(self.volume_type.extra_specs)
+ format_columns.DictColumn(self.volume_type.extra_specs)
)
arglist = [
'--encryption-type',
@@ -509,7 +513,7 @@ class TestTypeShow(TestType):
self.types_mock.get.assert_called_with(self.volume_type.id)
self.encryption_types_mock.get.assert_called_with(self.volume_type.id)
self.assertEqual(encryption_columns, columns)
- self.assertEqual(encryption_data, data)
+ self.assertItemEqual(encryption_data, data)
class TestTypeUnset(TestType):
@@ -587,3 +591,30 @@ class TestTypeUnset(TestType):
result = self.cmd.take_action(parsed_args)
self.encryption_types_mock.delete.assert_called_with(self.volume_type)
self.assertIsNone(result)
+
+
+class TestColumns(TestType):
+
+ def test_encryption_info_column_with_info(self):
+ fake_volume_type = volume_fakes.FakeType.create_one_type()
+ type_id = fake_volume_type.id
+
+ encryption_info = {
+ 'provider': 'LuksEncryptor',
+ 'cipher': None,
+ 'key_size': None,
+ 'control_location': 'front-end',
+ }
+ col = volume_type.EncryptionInfoColumn(type_id,
+ {type_id: encryption_info})
+ self.assertEqual(utils.format_dict(encryption_info),
+ col.human_readable())
+ self.assertEqual(encryption_info, col.machine_readable())
+
+ def test_encryption_info_column_without_info(self):
+ fake_volume_type = volume_fakes.FakeType.create_one_type()
+ type_id = fake_volume_type.id
+
+ col = volume_type.EncryptionInfoColumn(type_id, {})
+ self.assertEqual('-', col.human_readable())
+ self.assertIsNone(col.machine_readable())
diff --git a/openstackclient/tests/unit/volume/v1/test_volume.py b/openstackclient/tests/unit/volume/v1/test_volume.py
index eee5acd7..c4154555 100644
--- a/openstackclient/tests/unit/volume/v1/test_volume.py
+++ b/openstackclient/tests/unit/volume/v1/test_volume.py
@@ -17,6 +17,8 @@ import argparse
import mock
from mock import call
+
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -88,7 +90,7 @@ class TestVolumeCreate(TestVolume):
self.new_volume.display_description,
self.new_volume.id,
self.new_volume.display_name,
- utils.format_dict(self.new_volume.metadata),
+ format_columns.DictColumn(self.new_volume.metadata),
self.new_volume.size,
self.new_volume.snapshot_id,
self.new_volume.status,
@@ -134,7 +136,7 @@ class TestVolumeCreate(TestVolume):
None,
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_options(self):
arglist = [
@@ -178,7 +180,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_user_project_id(self):
# Return a project
@@ -225,7 +227,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_user_project_name(self):
# Return a project
@@ -272,7 +274,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_properties(self):
arglist = [
@@ -313,7 +315,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_image_id(self):
image = image_fakes.FakeImage.create_one_image()
@@ -356,7 +358,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_image_name(self):
image = image_fakes.FakeImage.create_one_image()
@@ -399,7 +401,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_with_source(self):
self.volumes_mock.get.return_value = self.new_volume
@@ -429,7 +431,7 @@ class TestVolumeCreate(TestVolume):
None,
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_with_bootable_and_readonly(self):
arglist = [
@@ -467,7 +469,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
self.volumes_mock.set_bootable.assert_called_with(
self.new_volume.id, True)
self.volumes_mock.update_readonly_flag.assert_called_with(
@@ -509,7 +511,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
self.volumes_mock.set_bootable.assert_called_with(
self.new_volume.id, False)
self.volumes_mock.update_readonly_flag.assert_called_with(
@@ -561,7 +563,7 @@ class TestVolumeCreate(TestVolume):
self.assertEqual(2, mock_error.call_count)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
self.volumes_mock.set_bootable.assert_called_with(
self.new_volume.id, True)
self.volumes_mock.update_readonly_flag.assert_called_with(
@@ -732,16 +734,13 @@ class TestVolumeList(TestVolume):
'Size',
'Attached to',
)
- server = _volume.attachments[0]['server_id']
- device = _volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = (
(
_volume.id,
_volume.display_name,
_volume.status,
_volume.size,
- msg,
+ volume.AttachmentsColumn(_volume.attachments),
),
)
@@ -767,7 +766,7 @@ class TestVolumeList(TestVolume):
columns, data = self.cmd.take_action(parsed_args)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, tuple(data))
+ self.assertListItemEqual(self.datalist, tuple(data))
def test_volume_list_name(self):
arglist = [
@@ -784,7 +783,7 @@ class TestVolumeList(TestVolume):
columns, data = self.cmd.take_action(parsed_args)
self.assertEqual(self.columns, tuple(columns))
- self.assertEqual(self.datalist, tuple(data))
+ self.assertListItemEqual(self.datalist, tuple(data))
def test_volume_list_status(self):
arglist = [
@@ -801,7 +800,7 @@ class TestVolumeList(TestVolume):
columns, data = self.cmd.take_action(parsed_args)
self.assertEqual(self.columns, tuple(columns))
- self.assertEqual(self.datalist, tuple(data))
+ self.assertListItemEqual(self.datalist, tuple(data))
def test_volume_list_all_projects(self):
arglist = [
@@ -818,7 +817,7 @@ class TestVolumeList(TestVolume):
columns, data = self.cmd.take_action(parsed_args)
self.assertEqual(self.columns, tuple(columns))
- self.assertEqual(self.datalist, tuple(data))
+ self.assertListItemEqual(self.datalist, tuple(data))
def test_volume_list_long(self):
arglist = [
@@ -855,10 +854,10 @@ class TestVolumeList(TestVolume):
self._volume.size,
self._volume.volume_type,
self._volume.bootable,
- self.msg,
- utils.format_dict(self._volume.metadata),
+ volume.AttachmentsColumn(self._volume.attachments),
+ format_columns.DictColumn(self._volume.metadata),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_with_limit(self):
arglist = [
@@ -883,7 +882,7 @@ class TestVolumeList(TestVolume):
'all_tenants': False, }
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, tuple(data))
+ self.assertListItemEqual(self.datalist, tuple(data))
def test_volume_list_negative_limit(self):
arglist = [
@@ -1251,7 +1250,7 @@ class TestVolumeShow(TestVolume):
self._volume.display_description,
self._volume.id,
self._volume.display_name,
- utils.format_dict(self._volume.metadata),
+ format_columns.DictColumn(self._volume.metadata),
self._volume.size,
self._volume.snapshot_id,
self._volume.status,
@@ -1274,7 +1273,7 @@ class TestVolumeShow(TestVolume):
self.volumes_mock.get.assert_called_with(self._volume.id)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_show_backward_compatibility(self):
arglist = [
@@ -1339,3 +1338,31 @@ class TestVolumeUnset(TestVolume):
self._volume.id, ['myprop']
)
self.assertIsNone(result)
+
+
+class TestColumns(TestVolume):
+
+ def test_attachments_column_without_server_cache(self):
+ _volume = volume_fakes.FakeVolume.create_one_volume()
+ server_id = _volume.attachments[0]['server_id']
+ device = _volume.attachments[0]['device']
+
+ col = volume.AttachmentsColumn(_volume.attachments, {})
+ self.assertEqual('Attached to %s on %s ' % (server_id, device),
+ col.human_readable())
+ self.assertEqual(_volume.attachments, col.machine_readable())
+
+ def test_attachments_column_with_server_cache(self):
+ _volume = volume_fakes.FakeVolume.create_one_volume()
+
+ server_id = _volume.attachments[0]['server_id']
+ device = _volume.attachments[0]['device']
+ fake_server = mock.Mock()
+ fake_server.name = 'fake-server-name'
+ server_cache = {server_id: fake_server}
+
+ col = volume.AttachmentsColumn(_volume.attachments, server_cache)
+ self.assertEqual(
+ 'Attached to %s on %s ' % ('fake-server-name', device),
+ col.human_readable())
+ self.assertEqual(_volume.attachments, col.machine_readable())
diff --git a/openstackclient/tests/unit/volume/v1/test_volume_backup.py b/openstackclient/tests/unit/volume/v1/test_volume_backup.py
index 22c1f8cf..20be6e46 100644
--- a/openstackclient/tests/unit/volume/v1/test_volume_backup.py
+++ b/openstackclient/tests/unit/volume/v1/test_volume_backup.py
@@ -100,7 +100,7 @@ class TestBackupCreate(TestBackup):
self.new_backup.description,
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_backup_create_without_name(self):
arglist = [
@@ -124,7 +124,7 @@ class TestBackupCreate(TestBackup):
self.new_backup.description,
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
class TestBackupDelete(TestBackup):
@@ -240,7 +240,7 @@ class TestBackupList(TestBackup):
b.status,
b.size,
b.availability_zone,
- b.volume_id,
+ volume_backup.VolumeIdColumn(b.volume_id),
b.container,
))
@@ -277,7 +277,7 @@ class TestBackupList(TestBackup):
search_opts=search_opts,
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_backup_list_with_options(self):
arglist = [
@@ -309,7 +309,7 @@ class TestBackupList(TestBackup):
search_opts=search_opts,
)
self.assertEqual(self.columns_long, columns)
- self.assertEqual(self.data_long, list(data))
+ self.assertListItemEqual(self.data_long, list(data))
class TestBackupRestore(TestBackup):
@@ -391,4 +391,4 @@ class TestBackupShow(TestBackup):
self.backups_mock.get.assert_called_with(self.backup.id)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
diff --git a/openstackclient/tests/unit/volume/v2/fakes.py b/openstackclient/tests/unit/volume/v2/fakes.py
index c245cbf6..5f976b06 100644
--- a/openstackclient/tests/unit/volume/v2/fakes.py
+++ b/openstackclient/tests/unit/volume/v2/fakes.py
@@ -17,7 +17,8 @@ import random
import uuid
import mock
-from osc_lib import utils as common_utils
+
+from osc_lib.cli import format_columns
from openstackclient.tests.unit import fakes
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
@@ -468,7 +469,7 @@ class FakeVolume(object):
if x == 'tags':
# The 'tags' should be format_list
data_list.append(
- common_utils.format_list(volume.info.get(x)))
+ format_columns.ListColumn(volume.info.get(x)))
else:
data_list.append(volume.info.get(x))
return tuple(data_list)
diff --git a/openstackclient/tests/unit/volume/v2/test_consistency_group.py b/openstackclient/tests/unit/volume/v2/test_consistency_group.py
index 6eeeae39..d2388182 100644
--- a/openstackclient/tests/unit/volume/v2/test_consistency_group.py
+++ b/openstackclient/tests/unit/volume/v2/test_consistency_group.py
@@ -15,6 +15,7 @@
import mock
from mock import call
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -250,7 +251,7 @@ class TestConsistencyGroupCreate(TestConsistencyGroup):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_consistency_group_create_from_source(self):
arglist = [
@@ -278,7 +279,7 @@ class TestConsistencyGroupCreate(TestConsistencyGroup):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_consistency_group_create_from_snapshot(self):
arglist = [
@@ -306,7 +307,7 @@ class TestConsistencyGroupCreate(TestConsistencyGroup):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
class TestConsistencyGroupDelete(TestConsistencyGroup):
@@ -439,7 +440,7 @@ class TestConsistencyGroupList(TestConsistencyGroup):
c.availability_zone,
c.name,
c.description,
- utils.format_list(c.volume_types)
+ format_columns.ListColumn(c.volume_types)
))
def setUp(self):
@@ -462,7 +463,7 @@ class TestConsistencyGroupList(TestConsistencyGroup):
self.consistencygroups_mock.list.assert_called_once_with(
detailed=True, search_opts={'all_tenants': False})
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_consistency_group_list_with_all_project(self):
arglist = [
@@ -479,7 +480,7 @@ class TestConsistencyGroupList(TestConsistencyGroup):
self.consistencygroups_mock.list.assert_called_once_with(
detailed=True, search_opts={'all_tenants': True})
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_consistency_group_list_with_long(self):
arglist = [
@@ -496,7 +497,7 @@ class TestConsistencyGroupList(TestConsistencyGroup):
self.consistencygroups_mock.list.assert_called_once_with(
detailed=True, search_opts={'all_tenants': False})
self.assertEqual(self.columns_long, columns)
- self.assertEqual(self.data_long, list(data))
+ self.assertListItemEqual(self.data_long, list(data))
class TestConsistencyGroupRemoveVolume(TestConsistencyGroup):
@@ -704,4 +705,4 @@ class TestConsistencyGroupShow(TestConsistencyGroup):
self.consistencygroups_mock.get.assert_called_once_with(
self.consistency_group.id)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
diff --git a/openstackclient/tests/unit/volume/v2/test_qos_specs.py b/openstackclient/tests/unit/volume/v2/test_qos_specs.py
index 2b935e20..454747f5 100644
--- a/openstackclient/tests/unit/volume/v2/test_qos_specs.py
+++ b/openstackclient/tests/unit/volume/v2/test_qos_specs.py
@@ -17,6 +17,8 @@ import copy
import mock
from mock import call
+
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -88,7 +90,7 @@ class TestQosCreate(TestQos):
self.new_qos_spec.consumer,
self.new_qos_spec.id,
self.new_qos_spec.name,
- utils.format_dict(self.new_qos_spec.specs)
+ format_columns.DictColumn(self.new_qos_spec.specs)
)
# Get the command object to test
@@ -111,7 +113,7 @@ class TestQosCreate(TestQos):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_qos_create_with_consumer(self):
arglist = [
@@ -132,7 +134,7 @@ class TestQosCreate(TestQos):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_qos_create_with_properties(self):
arglist = [
@@ -158,7 +160,7 @@ class TestQosCreate(TestQos):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
class TestQosDelete(TestQos):
@@ -318,8 +320,8 @@ class TestQosList(TestQos):
q.id,
q.name,
q.consumer,
- qos_association.name,
- utils.format_dict(q.specs),
+ format_columns.ListColumn([qos_association.name]),
+ format_columns.DictColumn(q.specs),
))
def setUp(self):
@@ -341,7 +343,7 @@ class TestQosList(TestQos):
self.qos_mock.list.assert_called_with()
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_qos_list_no_association(self):
self.qos_mock.reset_mock()
@@ -365,10 +367,10 @@ class TestQosList(TestQos):
self.qos_specs[1].id,
self.qos_specs[1].name,
self.qos_specs[1].consumer,
- None,
- utils.format_dict(self.qos_specs[1].specs),
+ format_columns.ListColumn(None),
+ format_columns.DictColumn(self.qos_specs[1].specs),
)
- self.assertEqual(ex_data, list(data))
+ self.assertListItemEqual(ex_data, list(data))
class TestQosSet(TestQos):
@@ -416,11 +418,11 @@ class TestQosShow(TestQos):
'properties'
)
data = (
- qos_association.name,
+ format_columns.ListColumn([qos_association.name]),
qos_spec.consumer,
qos_spec.id,
qos_spec.name,
- utils.format_dict(qos_spec.specs),
+ format_columns.DictColumn(qos_spec.specs),
)
def setUp(self):
@@ -448,7 +450,7 @@ class TestQosShow(TestQos):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, tuple(data))
+ self.assertItemEqual(self.data, tuple(data))
class TestQosUnset(TestQos):
diff --git a/openstackclient/tests/unit/volume/v2/test_type.py b/openstackclient/tests/unit/volume/v2/test_type.py
index 4023d55b..17915928 100644
--- a/openstackclient/tests/unit/volume/v2/test_type.py
+++ b/openstackclient/tests/unit/volume/v2/test_type.py
@@ -15,6 +15,7 @@
import mock
from mock import call
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -92,7 +93,7 @@ class TestTypeCreate(TestType):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_type_create_private(self):
arglist = [
@@ -118,7 +119,7 @@ class TestTypeCreate(TestType):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_public_type_create_with_project(self):
arglist = [
@@ -158,7 +159,7 @@ class TestTypeCreate(TestType):
)
encryption_data = (
self.new_volume_type.description,
- utils.format_dict(encryption_info),
+ format_columns.DictColumn(encryption_info),
self.new_volume_type.id,
True,
self.new_volume_type.name,
@@ -195,7 +196,7 @@ class TestTypeCreate(TestType):
body,
)
self.assertEqual(encryption_columns, columns)
- self.assertEqual(encryption_data, data)
+ self.assertItemEqual(encryption_data, data)
class TestTypeDelete(TestType):
@@ -305,7 +306,7 @@ class TestTypeList(TestType):
t.name,
t.is_public,
t.description,
- utils.format_dict(t.extra_specs),
+ format_columns.DictColumn(t.extra_specs),
))
def setUp(self):
@@ -329,7 +330,7 @@ class TestTypeList(TestType):
columns, data = self.cmd.take_action(parsed_args)
self.types_mock.list.assert_called_once_with(is_public=None)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_type_list_with_options(self):
arglist = [
@@ -347,7 +348,7 @@ class TestTypeList(TestType):
columns, data = self.cmd.take_action(parsed_args)
self.types_mock.list.assert_called_once_with(is_public=True)
self.assertEqual(self.columns_long, columns)
- self.assertEqual(self.data_long, list(data))
+ self.assertListItemEqual(self.data_long, list(data))
def test_type_list_with_private_option(self):
arglist = [
@@ -364,7 +365,7 @@ class TestTypeList(TestType):
columns, data = self.cmd.take_action(parsed_args)
self.types_mock.list.assert_called_once_with(is_public=False)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_type_list_with_default_option(self):
arglist = [
@@ -382,7 +383,7 @@ class TestTypeList(TestType):
columns, data = self.cmd.take_action(parsed_args)
self.types_mock.default.assert_called_once_with()
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data_with_default_type, list(data))
+ self.assertListItemEqual(self.data_with_default_type, list(data))
def test_type_list_with_encryption(self):
encryption_type = volume_fakes.FakeType.create_one_encryption_type(
@@ -401,13 +402,16 @@ class TestTypeList(TestType):
self.volume_types[0].id,
self.volume_types[0].name,
self.volume_types[0].is_public,
- utils.format_dict(encryption_info),
+ volume_type.EncryptionInfoColumn(
+ self.volume_types[0].id,
+ {self.volume_types[0].id: encryption_info}),
))
encryption_data.append((
self.volume_types[1].id,
self.volume_types[1].name,
self.volume_types[1].is_public,
- '-',
+ volume_type.EncryptionInfoColumn(
+ self.volume_types[1].id, {}),
))
self.encryption_types_mock.list.return_value = [encryption_type]
@@ -423,7 +427,7 @@ class TestTypeList(TestType):
self.encryption_types_mock.list.assert_called_once_with()
self.types_mock.list.assert_called_once_with(is_public=None)
self.assertEqual(encryption_columns, columns)
- self.assertEqual(encryption_data, list(data))
+ self.assertListItemEqual(encryption_data, list(data))
class TestTypeSet(TestType):
@@ -687,7 +691,7 @@ class TestTypeShow(TestType):
self.volume_type.id,
True,
self.volume_type.name,
- utils.format_dict(self.volume_type.extra_specs)
+ format_columns.DictColumn(self.volume_type.extra_specs)
)
self.types_mock.get.return_value = self.volume_type
@@ -709,7 +713,7 @@ class TestTypeShow(TestType):
self.types_mock.get.assert_called_with(self.volume_type.id)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, data)
+ self.assertItemEqual(self.data, data)
def test_type_show_with_access(self):
arglist = [
@@ -735,14 +739,14 @@ class TestTypeShow(TestType):
self.assertEqual(self.columns, columns)
private_type_data = (
- utils.format_list([type_access_list.project_id]),
+ format_columns.ListColumn([type_access_list.project_id]),
private_type.description,
private_type.id,
private_type.is_public,
private_type.name,
- utils.format_dict(private_type.extra_specs)
+ format_columns.DictColumn(private_type.extra_specs)
)
- self.assertEqual(private_type_data, data)
+ self.assertItemEqual(private_type_data, data)
def test_type_show_with_list_access_exec(self):
arglist = [
@@ -772,9 +776,9 @@ class TestTypeShow(TestType):
private_type.id,
private_type.is_public,
private_type.name,
- utils.format_dict(private_type.extra_specs)
+ format_columns.DictColumn(private_type.extra_specs)
)
- self.assertEqual(private_type_data, data)
+ self.assertItemEqual(private_type_data, data)
def test_type_show_with_encryption(self):
encryption_type = volume_fakes.FakeType.create_one_encryption_type()
@@ -800,11 +804,11 @@ class TestTypeShow(TestType):
encryption_data = (
None,
self.volume_type.description,
- utils.format_dict(encryption_info),
+ format_columns.DictColumn(encryption_info),
self.volume_type.id,
True,
self.volume_type.name,
- utils.format_dict(self.volume_type.extra_specs)
+ format_columns.DictColumn(self.volume_type.extra_specs)
)
arglist = [
'--encryption-type',
@@ -820,7 +824,7 @@ class TestTypeShow(TestType):
self.types_mock.get.assert_called_with(self.volume_type.id)
self.encryption_types_mock.get.assert_called_with(self.volume_type.id)
self.assertEqual(encryption_columns, columns)
- self.assertEqual(encryption_data, data)
+ self.assertItemEqual(encryption_data, data)
class TestTypeUnset(TestType):
@@ -923,3 +927,30 @@ class TestTypeUnset(TestType):
result = self.cmd.take_action(parsed_args)
self.encryption_types_mock.delete.assert_called_with(self.volume_type)
self.assertIsNone(result)
+
+
+class TestColumns(TestType):
+
+ def test_encryption_info_column_with_info(self):
+ fake_volume_type = volume_fakes.FakeType.create_one_type()
+ type_id = fake_volume_type.id
+
+ encryption_info = {
+ 'provider': 'LuksEncryptor',
+ 'cipher': None,
+ 'key_size': None,
+ 'control_location': 'front-end',
+ }
+ col = volume_type.EncryptionInfoColumn(type_id,
+ {type_id: encryption_info})
+ self.assertEqual(utils.format_dict(encryption_info),
+ col.human_readable())
+ self.assertEqual(encryption_info, col.machine_readable())
+
+ def test_encryption_info_column_without_info(self):
+ fake_volume_type = volume_fakes.FakeType.create_one_type()
+ type_id = fake_volume_type.id
+
+ col = volume_type.EncryptionInfoColumn(type_id, {})
+ self.assertEqual('-', col.human_readable())
+ self.assertIsNone(col.machine_readable())
diff --git a/openstackclient/tests/unit/volume/v2/test_volume.py b/openstackclient/tests/unit/volume/v2/test_volume.py
index 97da1601..332b50a7 100644
--- a/openstackclient/tests/unit/volume/v2/test_volume.py
+++ b/openstackclient/tests/unit/volume/v2/test_volume.py
@@ -16,6 +16,8 @@ import argparse
import mock
from mock import call
+
+from osc_lib.cli import format_columns
from osc_lib import exceptions
from osc_lib import utils
@@ -94,7 +96,7 @@ class TestVolumeCreate(TestVolume):
self.new_volume.description,
self.new_volume.id,
self.new_volume.name,
- utils.format_dict(self.new_volume.metadata),
+ format_columns.DictColumn(self.new_volume.metadata),
self.new_volume.size,
self.new_volume.snapshot_id,
self.new_volume.status,
@@ -135,7 +137,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_options(self):
consistency_group = (
@@ -181,7 +183,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_properties(self):
arglist = [
@@ -217,7 +219,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_image_id(self):
image = image_fakes.FakeImage.create_one_image()
@@ -255,7 +257,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_image_name(self):
image = image_fakes.FakeImage.create_one_image()
@@ -293,7 +295,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_with_snapshot(self):
snapshot = volume_fakes.FakeSnapshot.create_one_snapshot()
@@ -330,7 +332,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
def test_volume_create_with_bootable_and_readonly(self):
arglist = [
@@ -368,7 +370,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
self.volumes_mock.set_bootable.assert_called_with(
self.new_volume.id, True)
self.volumes_mock.update_readonly_flag.assert_called_with(
@@ -410,7 +412,7 @@ class TestVolumeCreate(TestVolume):
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
self.volumes_mock.set_bootable.assert_called_with(
self.new_volume.id, False)
self.volumes_mock.update_readonly_flag.assert_called_with(
@@ -462,7 +464,7 @@ class TestVolumeCreate(TestVolume):
self.assertEqual(2, mock_error.call_count)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.datalist, data)
+ self.assertItemEqual(self.datalist, data)
self.volumes_mock.set_bootable.assert_called_with(
self.new_volume.id, True)
self.volumes_mock.update_readonly_flag.assert_called_with(
@@ -672,17 +674,14 @@ class TestVolumeList(TestVolume):
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_project(self):
arglist = [
@@ -715,17 +714,14 @@ class TestVolumeList(TestVolume):
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_project_domain(self):
arglist = [
@@ -760,17 +756,14 @@ class TestVolumeList(TestVolume):
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_user(self):
arglist = [
@@ -800,19 +793,16 @@ class TestVolumeList(TestVolume):
marker=None,
limit=None,
)
-
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
+
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_user_domain(self):
arglist = [
@@ -847,17 +837,14 @@ class TestVolumeList(TestVolume):
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_name(self):
arglist = [
@@ -890,17 +877,14 @@ class TestVolumeList(TestVolume):
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_status(self):
arglist = [
@@ -933,17 +917,14 @@ class TestVolumeList(TestVolume):
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_all_projects(self):
arglist = [
@@ -976,17 +957,14 @@ class TestVolumeList(TestVolume):
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_long(self):
arglist = [
@@ -1030,9 +1008,6 @@ class TestVolumeList(TestVolume):
]
self.assertEqual(collist, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
@@ -1040,10 +1015,10 @@ class TestVolumeList(TestVolume):
self.mock_volume.size,
self.mock_volume.volume_type,
self.mock_volume.bootable,
- msg,
- utils.format_dict(self.mock_volume.metadata),
+ volume.AttachmentsColumn(self.mock_volume.attachments),
+ format_columns.DictColumn(self.mock_volume.metadata),
), )
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_with_marker_and_limit(self):
arglist = [
@@ -1064,15 +1039,12 @@ class TestVolumeList(TestVolume):
self.assertEqual(self.columns, columns)
- server = self.mock_volume.attachments[0]['server_id']
- device = self.mock_volume.attachments[0]['device']
- msg = 'Attached to %s on %s ' % (server, device)
datalist = ((
self.mock_volume.id,
self.mock_volume.name,
self.mock_volume.status,
self.mock_volume.size,
- msg,
+ volume.AttachmentsColumn(self.mock_volume.attachments),
), )
self.volumes_mock.list.assert_called_once_with(
@@ -1085,7 +1057,7 @@ class TestVolumeList(TestVolume):
'name': None,
'all_tenants': False, }
)
- self.assertEqual(datalist, tuple(data))
+ self.assertListItemEqual(datalist, tuple(data))
def test_volume_list_negative_limit(self):
arglist = [
@@ -1479,7 +1451,7 @@ class TestVolumeShow(TestVolume):
volume_fakes.FakeVolume.get_volume_columns(self._volume),
columns)
- self.assertEqual(
+ self.assertItemEqual(
volume_fakes.FakeVolume.get_volume_data(self._volume),
data)
@@ -1562,3 +1534,31 @@ class TestVolumeUnset(TestVolume):
self.new_volume.id, parsed_args.image_property)
self.volumes_mock.delete_metadata.assert_called_with(
self.new_volume.id, parsed_args.property)
+
+
+class TestColumns(TestVolume):
+
+ def test_attachments_column_without_server_cache(self):
+ _volume = volume_fakes.FakeVolume.create_one_volume()
+ server_id = _volume.attachments[0]['server_id']
+ device = _volume.attachments[0]['device']
+
+ col = volume.AttachmentsColumn(_volume.attachments, {})
+ self.assertEqual('Attached to %s on %s ' % (server_id, device),
+ col.human_readable())
+ self.assertEqual(_volume.attachments, col.machine_readable())
+
+ def test_attachments_column_with_server_cache(self):
+ _volume = volume_fakes.FakeVolume.create_one_volume()
+
+ server_id = _volume.attachments[0]['server_id']
+ device = _volume.attachments[0]['device']
+ fake_server = mock.Mock()
+ fake_server.name = 'fake-server-name'
+ server_cache = {server_id: fake_server}
+
+ col = volume.AttachmentsColumn(_volume.attachments, server_cache)
+ self.assertEqual(
+ 'Attached to %s on %s ' % ('fake-server-name', device),
+ col.human_readable())
+ self.assertEqual(_volume.attachments, col.machine_readable())
diff --git a/openstackclient/tests/unit/volume/v2/test_volume_backup.py b/openstackclient/tests/unit/volume/v2/test_volume_backup.py
index d0d1da3b..30c7915d 100644
--- a/openstackclient/tests/unit/volume/v2/test_volume_backup.py
+++ b/openstackclient/tests/unit/volume/v2/test_volume_backup.py
@@ -271,7 +271,7 @@ class TestBackupList(TestBackup):
b.status,
b.size,
b.availability_zone,
- b.volume_id,
+ volume_backup.VolumeIdColumn(b.volume_id),
b.container,
))
@@ -314,7 +314,7 @@ class TestBackupList(TestBackup):
limit=None,
)
self.assertEqual(self.columns, columns)
- self.assertEqual(self.data, list(data))
+ self.assertListItemEqual(self.data, list(data))
def test_backup_list_with_options(self):
arglist = [
@@ -353,7 +353,7 @@ class TestBackupList(TestBackup):
limit=3,
)
self.assertEqual(self.columns_long, columns)
- self.assertEqual(self.data_long, list(data))
+ self.assertListItemEqual(self.data_long, list(data))
class TestBackupRestore(TestBackup):
diff --git a/openstackclient/volume/v1/qos_specs.py b/openstackclient/volume/v1/qos_specs.py
index 26c91829..0b6a7fa0 100644
--- a/openstackclient/volume/v1/qos_specs.py
+++ b/openstackclient/volume/v1/qos_specs.py
@@ -17,6 +17,7 @@
import logging
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -95,7 +96,8 @@ class CreateQos(command.ShowOne):
qos_spec = volume_client.qos_specs.create(parsed_args.name, specs)
qos_spec._info.update(
- {'properties': utils.format_dict(qos_spec._info.pop('specs'))}
+ {'properties':
+ format_columns.DictColumn(qos_spec._info.pop('specs'))}
)
return zip(*sorted(six.iteritems(qos_spec._info)))
@@ -208,8 +210,8 @@ class ListQos(command.Lister):
(utils.get_dict_properties(
s._info, columns,
formatters={
- 'Specs': utils.format_dict,
- 'Associations': utils.format_list
+ 'Specs': format_columns.DictColumn,
+ 'Associations': format_columns.ListColumn
},
) for s in qos_specs_list))
@@ -265,10 +267,11 @@ class ShowQos(command.ShowOne):
associations = [association.name
for association in qos_associations]
qos_spec._info.update({
- 'associations': utils.format_list(associations)
+ 'associations': format_columns.ListColumn(associations)
})
qos_spec._info.update(
- {'properties': utils.format_dict(qos_spec._info.pop('specs'))})
+ {'properties':
+ format_columns.DictColumn(qos_spec._info.pop('specs'))})
return zip(*sorted(six.iteritems(qos_spec._info)))
diff --git a/openstackclient/volume/v1/volume.py b/openstackclient/volume/v1/volume.py
index b29429ef..36c7ef89 100644
--- a/openstackclient/volume/v1/volume.py
+++ b/openstackclient/volume/v1/volume.py
@@ -16,8 +16,11 @@
"""Volume v1 Volume action implementations"""
import argparse
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -30,6 +33,37 @@ from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
+class AttachmentsColumn(cliff_columns.FormattableColumn):
+ """Formattable column for attachments column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes server_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(AttachmentsColumn, server_cache)``.
+ """
+
+ def __init__(self, value, server_cache=None):
+ super(AttachmentsColumn, self).__init__(value)
+ self._server_cache = server_cache or {}
+
+ def human_readable(self):
+ """Return a formatted string of a volume's attached instances
+
+ :rtype: a string of formatted instances
+ """
+
+ msg = ''
+ for attachment in self._value:
+ server = attachment['server_id']
+ if server in self._server_cache.keys():
+ server = self._server_cache[server].name
+ device = attachment['device']
+ msg += 'Attached to %s on %s ' % (server, device)
+ return msg
+
+
def _check_size_arg(args):
"""Check whether --size option is required or not.
@@ -207,7 +241,8 @@ class CreateVolume(command.ShowOne):
# Map 'metadata' column to 'properties'
volume._info.update(
{
- 'properties': utils.format_dict(volume._info.pop('metadata')),
+ 'properties':
+ format_columns.DictColumn(volume._info.pop('metadata')),
'type': volume._info.pop('volume_type'),
},
)
@@ -307,22 +342,6 @@ class ListVolume(command.Lister):
volume_client = self.app.client_manager.volume
compute_client = self.app.client_manager.compute
- def _format_attach(attachments):
- """Return a formatted string of a volume's attached instances
-
- :param attachments: a volume.attachments field
- :rtype: a string of formatted instances
- """
-
- msg = ''
- for attachment in attachments:
- server = attachment['server_id']
- if server in server_cache.keys():
- server = server_cache[server].name
- device = attachment['device']
- msg += 'Attached to %s on %s ' % (server, device)
- return msg
-
if parsed_args.long:
columns = (
'ID',
@@ -368,6 +387,8 @@ class ListVolume(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ AttachmentsColumnWithCache = functools.partial(
+ AttachmentsColumn, server_cache=server_cache)
search_opts = {
'all_tenants': parsed_args.all_projects,
@@ -385,8 +406,8 @@ class ListVolume(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Metadata': utils.format_dict,
- 'Attachments': _format_attach},
+ formatters={'Metadata': format_columns.DictColumn,
+ 'Attachments': AttachmentsColumnWithCache},
) for s in data))
@@ -575,7 +596,8 @@ class ShowVolume(command.ShowOne):
# Map 'metadata' column to 'properties'
volume._info.update(
{
- 'properties': utils.format_dict(volume._info.pop('metadata')),
+ 'properties':
+ format_columns.DictColumn(volume._info.pop('metadata')),
'type': volume._info.pop('volume_type'),
},
)
diff --git a/openstackclient/volume/v1/volume_backup.py b/openstackclient/volume/v1/volume_backup.py
index 9af32705..2daa23cb 100644
--- a/openstackclient/volume/v1/volume_backup.py
+++ b/openstackclient/volume/v1/volume_backup.py
@@ -16,8 +16,10 @@
"""Volume v1 Backup action implementations"""
import copy
+import functools
import logging
+from cliff import columns as cliff_columns
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
@@ -29,6 +31,33 @@ from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
+class VolumeIdColumn(cliff_columns.FormattableColumn):
+ """Formattable column for volume ID column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes volume_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(VolumeIdColumn, volume_cache)``.
+ """
+
+ def __init__(self, value, volume_cache=None):
+ super(VolumeIdColumn, self).__init__(value)
+ self._volume_cache = volume_cache or {}
+
+ def human_readable(self):
+ """Return a volume name if available
+
+ :rtype: either the volume ID or name
+ """
+ volume_id = self._value
+ volume = volume_id
+ if volume_id in self._volume_cache.keys():
+ volume = self._volume_cache[volume_id].display_name
+ return volume
+
+
class CreateVolumeBackup(command.ShowOne):
_description = _("Create new volume backup")
@@ -149,18 +178,6 @@ class ListVolumeBackup(command.Lister):
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
- def _format_volume_id(volume_id):
- """Return a volume name if available
-
- :param volume_id: a volume ID
- :rtype: either the volume ID or name
- """
-
- volume = volume_id
- if volume_id in volume_cache.keys():
- volume = volume_cache[volume_id].display_name
- return volume
-
if parsed_args.long:
columns = ['ID', 'Name', 'Description', 'Status', 'Size',
'Availability Zone', 'Volume ID', 'Container']
@@ -178,6 +195,8 @@ class ListVolumeBackup(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ VolumeIdColumnWithCache = functools.partial(VolumeIdColumn,
+ volume_cache=volume_cache)
filter_volume_id = None
if parsed_args.volume:
@@ -196,7 +215,7 @@ class ListVolumeBackup(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Volume ID': _format_volume_id},
+ formatters={'Volume ID': VolumeIdColumnWithCache},
) for s in data))
diff --git a/openstackclient/volume/v1/volume_snapshot.py b/openstackclient/volume/v1/volume_snapshot.py
index 3e83da5a..50f81771 100644
--- a/openstackclient/volume/v1/volume_snapshot.py
+++ b/openstackclient/volume/v1/volume_snapshot.py
@@ -16,8 +16,11 @@
"""Volume v1 Snapshot action implementations"""
import copy
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -30,6 +33,33 @@ from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
+class VolumeIdColumn(cliff_columns.FormattableColumn):
+ """Formattable column for volume ID column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes volume_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(VolumeIdColumn, volume_cache)``.
+ """
+
+ def __init__(self, value, volume_cache=None):
+ super(VolumeIdColumn, self).__init__(value)
+ self._volume_cache = volume_cache or {}
+
+ def human_readable(self):
+ """Return a volume name if available
+
+ :rtype: either the volume ID or name
+ """
+ volume_id = self._value
+ volume = volume_id
+ if volume_id in self._volume_cache.keys():
+ volume = self._volume_cache[volume_id].display_name
+ return volume
+
+
class CreateVolumeSnapshot(command.ShowOne):
_description = _("Create new volume snapshot")
@@ -76,7 +106,8 @@ class CreateVolumeSnapshot(command.ShowOne):
)
snapshot._info.update(
- {'properties': utils.format_dict(snapshot._info.pop('metadata'))}
+ {'properties':
+ format_columns.DictColumn(snapshot._info.pop('metadata'))}
)
return zip(*sorted(six.iteritems(snapshot._info)))
@@ -160,18 +191,6 @@ class ListVolumeSnapshot(command.Lister):
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
- def _format_volume_id(volume_id):
- """Return a volume name if available
-
- :param volume_id: a volume ID
- :rtype: either the volume ID or name
- """
-
- volume = volume_id
- if volume_id in volume_cache.keys():
- volume = volume_cache[volume_id].display_name
- return volume
-
if parsed_args.long:
columns = ['ID', 'Display Name', 'Display Description', 'Status',
'Size', 'Created At', 'Volume ID', 'Metadata']
@@ -195,6 +214,8 @@ class ListVolumeSnapshot(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ VolumeIdColumnWithCache = functools.partial(VolumeIdColumn,
+ volume_cache=volume_cache)
volume_id = None
if parsed_args.volume:
@@ -213,8 +234,8 @@ class ListVolumeSnapshot(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Metadata': utils.format_dict,
- 'Volume ID': _format_volume_id},
+ formatters={'Metadata': format_columns.DictColumn,
+ 'Volume ID': VolumeIdColumnWithCache},
) for s in data))
@@ -317,7 +338,8 @@ class ShowVolumeSnapshot(command.ShowOne):
parsed_args.snapshot)
snapshot._info.update(
- {'properties': utils.format_dict(snapshot._info.pop('metadata'))}
+ {'properties':
+ format_columns.DictColumn(snapshot._info.pop('metadata'))}
)
return zip(*sorted(six.iteritems(snapshot._info)))
diff --git a/openstackclient/volume/v1/volume_type.py b/openstackclient/volume/v1/volume_type.py
index b4d8eaca..e744e92f 100644
--- a/openstackclient/volume/v1/volume_type.py
+++ b/openstackclient/volume/v1/volume_type.py
@@ -15,8 +15,11 @@
"""Volume v1 Type action implementations"""
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -29,6 +32,36 @@ from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
+class EncryptionInfoColumn(cliff_columns.FormattableColumn):
+ """Formattable column for encryption info column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes encryption_data as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(EncryptionInfoColumn encryption_data)``.
+ """
+
+ def __init__(self, value, encryption_data=None):
+ super(EncryptionInfoColumn, self).__init__(value)
+ self._encryption_data = encryption_data or {}
+
+ def _get_encryption_info(self):
+ type_id = self._value
+ return self._encryption_data.get(type_id)
+
+ def human_readable(self):
+ encryption_info = self._get_encryption_info()
+ if encryption_info:
+ return utils.format_dict(encryption_info)
+ else:
+ return '-'
+
+ def machine_readable(self):
+ return self._get_encryption_info()
+
+
def _create_encryption_type(volume_client, volume_type, parsed_args):
if not parsed_args.encryption_provider:
msg = _("'--encryption-provider' should be specified while "
@@ -110,7 +143,8 @@ class CreateVolumeType(command.ShowOne):
volume_type._info.pop('extra_specs')
if parsed_args.property:
result = volume_type.set_keys(parsed_args.property)
- volume_type._info.update({'properties': utils.format_dict(result)})
+ volume_type._info.update(
+ {'properties': format_columns.DictColumn(result)})
if (parsed_args.encryption_provider or
parsed_args.encryption_cipher or
parsed_args.encryption_key_size or
@@ -125,7 +159,7 @@ class CreateVolumeType(command.ShowOne):
# add encryption info in result
encryption._info.pop("volume_type_id", None)
volume_type._info.update(
- {'encryption': utils.format_dict(encryption._info)})
+ {'encryption': format_columns.DictColumn(encryption._info)})
volume_type._info.pop("os-volume-type-access:is_public", None)
return zip(*sorted(six.iteritems(volume_type._info)))
@@ -196,12 +230,7 @@ class ListVolumeType(command.Lister):
column_headers = ['ID', 'Name', 'Is Public']
data = volume_client.volume_types.list()
- def _format_encryption_info(type_id, encryption_data=None):
- encryption_data = encryption
- encryption_info = '-'
- if type_id in encryption_data.keys():
- encryption_info = encryption_data[type_id]
- return encryption_info
+ formatters = {'Extra Specs': format_columns.DictColumn}
if parsed_args.encryption_type:
encryption = {}
@@ -218,18 +247,21 @@ class ListVolumeType(command.Lister):
for key in del_key:
d._info.pop(key, None)
# save the encryption information with their volume type ID
- encryption[volume_type_id] = utils.format_dict(d._info)
+ encryption[volume_type_id] = d._info
# We need to get volume type ID, then show encryption
# information according to the ID, so use "id" to keep
# difference to the real "ID" column.
columns += ['id']
column_headers += ['Encryption']
+ _EncryptionInfoColumn = functools.partial(
+ EncryptionInfoColumn, encryption_data=encryption)
+ formatters['id'] = _EncryptionInfoColumn
+
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Extra Specs': utils.format_dict,
- 'id': _format_encryption_info},
+ formatters=formatters,
) for s in data))
@@ -340,7 +372,8 @@ class ShowVolumeType(command.ShowOne):
volume_client = self.app.client_manager.volume
volume_type = utils.find_resource(
volume_client.volume_types, parsed_args.volume_type)
- properties = utils.format_dict(volume_type._info.pop('extra_specs'))
+ properties = format_columns.DictColumn(
+ volume_type._info.pop('extra_specs'))
volume_type._info.update({'properties': properties})
if parsed_args.encryption_type:
# show encryption type information for this volume type
@@ -349,7 +382,8 @@ class ShowVolumeType(command.ShowOne):
volume_type.id)
encryption._info.pop("volume_type_id", None)
volume_type._info.update(
- {'encryption': utils.format_dict(encryption._info)})
+ {'encryption':
+ format_columns.DictColumn(encryption._info)})
except Exception as e:
LOG.error(_("Failed to display the encryption information "
"of this volume type: %s"), e)
diff --git a/openstackclient/volume/v2/consistency_group.py b/openstackclient/volume/v2/consistency_group.py
index 0a932f84..26dd8ffc 100644
--- a/openstackclient/volume/v2/consistency_group.py
+++ b/openstackclient/volume/v2/consistency_group.py
@@ -16,6 +16,7 @@
import logging
+from osc_lib.cli import format_columns
from osc_lib.command import command
from osc_lib import exceptions
from osc_lib import utils
@@ -238,7 +239,7 @@ class ListConsistencyGroup(command.Lister):
return (columns, (
utils.get_item_properties(
s, columns,
- formatters={'Volume Types': utils.format_list})
+ formatters={'Volume Types': format_columns.ListColumn})
for s in consistency_groups))
diff --git a/openstackclient/volume/v2/qos_specs.py b/openstackclient/volume/v2/qos_specs.py
index c7160581..3037d34a 100644
--- a/openstackclient/volume/v2/qos_specs.py
+++ b/openstackclient/volume/v2/qos_specs.py
@@ -17,6 +17,7 @@
import logging
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -96,7 +97,8 @@ class CreateQos(command.ShowOne):
qos_spec = volume_client.qos_specs.create(parsed_args.name, specs)
qos_spec._info.update(
- {'properties': utils.format_dict(qos_spec._info.pop('specs'))}
+ {'properties':
+ format_columns.DictColumn(qos_spec._info.pop('specs'))}
)
return zip(*sorted(six.iteritems(qos_spec._info)))
@@ -210,8 +212,8 @@ class ListQos(command.Lister):
(utils.get_dict_properties(
s._info, columns,
formatters={
- 'Specs': utils.format_dict,
- 'Associations': utils.format_list
+ 'Specs': format_columns.DictColumn,
+ 'Associations': format_columns.ListColumn
},
) for s in qos_specs_list))
@@ -267,10 +269,11 @@ class ShowQos(command.ShowOne):
associations = [association.name
for association in qos_associations]
qos_spec._info.update({
- 'associations': utils.format_list(associations)
+ 'associations': format_columns.ListColumn(associations)
})
qos_spec._info.update(
- {'properties': utils.format_dict(qos_spec._info.pop('specs'))})
+ {'properties':
+ format_columns.DictColumn(qos_spec._info.pop('specs'))})
return zip(*sorted(six.iteritems(qos_spec._info)))
diff --git a/openstackclient/volume/v2/volume.py b/openstackclient/volume/v2/volume.py
index ef65d097..17ccd3d3 100644
--- a/openstackclient/volume/v2/volume.py
+++ b/openstackclient/volume/v2/volume.py
@@ -16,8 +16,11 @@
import argparse
import copy
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -31,6 +34,37 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
+class AttachmentsColumn(cliff_columns.FormattableColumn):
+ """Formattable column for attachments column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes server_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(AttachmentsColumn, server_cache)``.
+ """
+
+ def __init__(self, value, server_cache=None):
+ super(AttachmentsColumn, self).__init__(value)
+ self._server_cache = server_cache or {}
+
+ def human_readable(self):
+ """Return a formatted string of a volume's attached instances
+
+ :rtype: a string of formatted instances
+ """
+
+ msg = ''
+ for attachment in self._value:
+ server = attachment['server_id']
+ if server in self._server_cache.keys():
+ server = self._server_cache[server].name
+ device = attachment['device']
+ msg += 'Attached to %s on %s ' % (server, device)
+ return msg
+
+
def _check_size_arg(args):
"""Check whether --size option is required or not.
@@ -212,7 +246,8 @@ class CreateVolume(command.ShowOne):
# Remove key links from being displayed
volume._info.update(
{
- 'properties': utils.format_dict(volume._info.pop('metadata')),
+ 'properties':
+ format_columns.DictColumn(volume._info.pop('metadata')),
'type': volume._info.pop('volume_type')
}
)
@@ -331,22 +366,6 @@ class ListVolume(command.Lister):
compute_client = self.app.client_manager.compute
identity_client = self.app.client_manager.identity
- def _format_attach(attachments):
- """Return a formatted string of a volume's attached instances
-
- :param attachments: a volume.attachments field
- :rtype: a string of formatted instances
- """
-
- msg = ''
- for attachment in attachments:
- server = attachment['server_id']
- if server in server_cache:
- server = server_cache[server].name
- device = attachment['device']
- msg += 'Attached to %s on %s ' % (server, device)
- return msg
-
if parsed_args.long:
columns = [
'ID',
@@ -381,6 +400,8 @@ class ListVolume(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ AttachmentsColumnWithCache = functools.partial(
+ AttachmentsColumn, server_cache=server_cache)
project_id = None
if parsed_args.project:
@@ -417,8 +438,8 @@ class ListVolume(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Metadata': utils.format_dict,
- 'Attachments': _format_attach},
+ formatters={'Metadata': format_columns.DictColumn,
+ 'Attachments': AttachmentsColumnWithCache},
) for s in data))
@@ -722,7 +743,8 @@ class ShowVolume(command.ShowOne):
# 'volume_type' --> 'type'
volume._info.update(
{
- 'properties': utils.format_dict(volume._info.pop('metadata')),
+ 'properties':
+ format_columns.DictColumn(volume._info.pop('metadata')),
'type': volume._info.pop('volume_type'),
},
)
diff --git a/openstackclient/volume/v2/volume_backup.py b/openstackclient/volume/v2/volume_backup.py
index 1d2b0cde..4d0d54c1 100644
--- a/openstackclient/volume/v2/volume_backup.py
+++ b/openstackclient/volume/v2/volume_backup.py
@@ -15,8 +15,10 @@
"""Volume v2 Backup action implementations"""
import copy
+import functools
import logging
+from cliff import columns as cliff_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -29,6 +31,33 @@ from openstackclient.i18n import _
LOG = logging.getLogger(__name__)
+class VolumeIdColumn(cliff_columns.FormattableColumn):
+ """Formattable column for volume ID column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes volume_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(VolumeIdColumn, volume_cache)``.
+ """
+
+ def __init__(self, value, volume_cache=None):
+ super(VolumeIdColumn, self).__init__(value)
+ self._volume_cache = volume_cache or {}
+
+ def human_readable(self):
+ """Return a volume name if available
+
+ :rtype: either the volume ID or name
+ """
+ volume_id = self._value
+ volume = volume_id
+ if volume_id in self._volume_cache.keys():
+ volume = self._volume_cache[volume_id].name
+ return volume
+
+
class CreateVolumeBackup(command.ShowOne):
_description = _("Create new volume backup")
@@ -189,18 +218,6 @@ class ListVolumeBackup(command.Lister):
def take_action(self, parsed_args):
volume_client = self.app.client_manager.volume
- def _format_volume_id(volume_id):
- """Return a volume name if available
-
- :param volume_id: a volume ID
- :rtype: either the volume ID or name
- """
-
- volume = volume_id
- if volume_id in volume_cache.keys():
- volume = volume_cache[volume_id].name
- return volume
-
if parsed_args.long:
columns = ['ID', 'Name', 'Description', 'Status', 'Size',
'Availability Zone', 'Volume ID', 'Container']
@@ -218,6 +235,8 @@ class ListVolumeBackup(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ _VolumeIdColumn = functools.partial(VolumeIdColumn,
+ volume_cache=volume_cache)
filter_volume_id = None
if parsed_args.volume:
@@ -242,7 +261,7 @@ class ListVolumeBackup(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Volume ID': _format_volume_id},
+ formatters={'Volume ID': _VolumeIdColumn},
) for s in data))
diff --git a/openstackclient/volume/v2/volume_snapshot.py b/openstackclient/volume/v2/volume_snapshot.py
index fe969410..2b26ae32 100644
--- a/openstackclient/volume/v2/volume_snapshot.py
+++ b/openstackclient/volume/v2/volume_snapshot.py
@@ -15,8 +15,11 @@
"""Volume v2 snapshot action implementations"""
import copy
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -30,6 +33,33 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
+class VolumeIdColumn(cliff_columns.FormattableColumn):
+ """Formattable column for volume ID column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes volume_cache as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(VolumeIdColumn, volume_cache)``.
+ """
+
+ def __init__(self, value, volume_cache=None):
+ super(VolumeIdColumn, self).__init__(value)
+ self._volume_cache = volume_cache or {}
+
+ def human_readable(self):
+ """Return a volume name if available
+
+ :rtype: either the volume ID or name
+ """
+ volume_id = self._value
+ volume = volume_id
+ if volume_id in self._volume_cache.keys():
+ volume = self._volume_cache[volume_id].name
+ return volume
+
+
class CreateVolumeSnapshot(command.ShowOne):
_description = _("Create new volume snapshot")
@@ -107,7 +137,8 @@ class CreateVolumeSnapshot(command.ShowOne):
metadata=parsed_args.property,
)
snapshot._info.update(
- {'properties': utils.format_dict(snapshot._info.pop('metadata'))}
+ {'properties':
+ format_columns.DictColumn(snapshot._info.pop('metadata'))}
)
return zip(*sorted(six.iteritems(snapshot._info)))
@@ -216,18 +247,6 @@ class ListVolumeSnapshot(command.Lister):
volume_client = self.app.client_manager.volume
identity_client = self.app.client_manager.identity
- def _format_volume_id(volume_id):
- """Return a volume name if available
-
- :param volume_id: a volume ID
- :rtype: either the volume ID or name
- """
-
- volume = volume_id
- if volume_id in volume_cache.keys():
- volume = volume_cache[volume_id].name
- return volume
-
if parsed_args.long:
columns = ['ID', 'Name', 'Description', 'Status',
'Size', 'Created At', 'Volume ID', 'Metadata']
@@ -246,6 +265,8 @@ class ListVolumeSnapshot(command.Lister):
except Exception:
# Just forget it if there's any trouble
pass
+ _VolumeIdColumn = functools.partial(VolumeIdColumn,
+ volume_cache=volume_cache)
volume_id = None
if parsed_args.volume:
@@ -279,8 +300,8 @@ class ListVolumeSnapshot(command.Lister):
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Metadata': utils.format_dict,
- 'Volume ID': _format_volume_id},
+ formatters={'Metadata': format_columns.DictColumn,
+ 'Volume ID': _VolumeIdColumn},
) for s in data))
@@ -402,7 +423,8 @@ class ShowVolumeSnapshot(command.ShowOne):
snapshot = utils.find_resource(
volume_client.volume_snapshots, parsed_args.snapshot)
snapshot._info.update(
- {'properties': utils.format_dict(snapshot._info.pop('metadata'))}
+ {'properties':
+ format_columns.DictColumn(snapshot._info.pop('metadata'))}
)
return zip(*sorted(six.iteritems(snapshot._info)))
diff --git a/openstackclient/volume/v2/volume_type.py b/openstackclient/volume/v2/volume_type.py
index 749d1dd6..54b1f497 100644
--- a/openstackclient/volume/v2/volume_type.py
+++ b/openstackclient/volume/v2/volume_type.py
@@ -14,8 +14,11 @@
"""Volume v2 Type action implementations"""
+import functools
import logging
+from cliff import columns as cliff_columns
+from osc_lib.cli import format_columns
from osc_lib.cli import parseractions
from osc_lib.command import command
from osc_lib import exceptions
@@ -29,6 +32,36 @@ from openstackclient.identity import common as identity_common
LOG = logging.getLogger(__name__)
+class EncryptionInfoColumn(cliff_columns.FormattableColumn):
+ """Formattable column for encryption info column.
+
+ Unlike the parent FormattableColumn class, the initializer of the
+ class takes encryption_data as the second argument.
+ osc_lib.utils.get_item_properties instantiate cliff FormattableColumn
+ object with a single parameter "column value", so you need to pass
+ a partially initialized class like
+ ``functools.partial(EncryptionInfoColumn encryption_data)``.
+ """
+
+ def __init__(self, value, encryption_data=None):
+ super(EncryptionInfoColumn, self).__init__(value)
+ self._encryption_data = encryption_data or {}
+
+ def _get_encryption_info(self):
+ type_id = self._value
+ return self._encryption_data.get(type_id)
+
+ def human_readable(self):
+ encryption_info = self._get_encryption_info()
+ if encryption_info:
+ return utils.format_dict(encryption_info)
+ else:
+ return '-'
+
+ def machine_readable(self):
+ return self._get_encryption_info()
+
+
def _create_encryption_type(volume_client, volume_type, parsed_args):
if not parsed_args.encryption_provider:
msg = _("'--encryption-provider' should be specified while "
@@ -183,7 +216,8 @@ class CreateVolumeType(command.ShowOne):
LOG.error(msg % {'project': parsed_args.project, 'e': e})
if parsed_args.property:
result = volume_type.set_keys(parsed_args.property)
- volume_type._info.update({'properties': utils.format_dict(result)})
+ volume_type._info.update(
+ {'properties': format_columns.DictColumn(result)})
if (parsed_args.encryption_provider or
parsed_args.encryption_cipher or
parsed_args.encryption_key_size or
@@ -198,7 +232,7 @@ class CreateVolumeType(command.ShowOne):
# add encryption info in result
encryption._info.pop("volume_type_id", None)
volume_type._info.update(
- {'encryption': utils.format_dict(encryption._info)})
+ {'encryption': format_columns.DictColumn(encryption._info)})
volume_type._info.pop("os-volume-type-access:is_public", None)
return zip(*sorted(six.iteritems(volume_type._info)))
@@ -296,12 +330,7 @@ class ListVolumeType(command.Lister):
data = volume_client.volume_types.list(
is_public=is_public)
- def _format_encryption_info(type_id, encryption_data=None):
- encryption_data = encryption
- encryption_info = '-'
- if type_id in encryption_data.keys():
- encryption_info = encryption_data[type_id]
- return encryption_info
+ formatters = {'Extra Specs': format_columns.DictColumn}
if parsed_args.encryption_type:
encryption = {}
@@ -318,18 +347,21 @@ class ListVolumeType(command.Lister):
for key in del_key:
d._info.pop(key, None)
# save the encryption information with their volume type ID
- encryption[volume_type_id] = utils.format_dict(d._info)
+ encryption[volume_type_id] = d._info
# We need to get volume type ID, then show encryption
# information according to the ID, so use "id" to keep
# difference to the real "ID" column.
columns += ['id']
column_headers += ['Encryption']
+ _EncryptionInfoColumn = functools.partial(
+ EncryptionInfoColumn, encryption_data=encryption)
+ formatters['id'] = _EncryptionInfoColumn
+
return (column_headers,
(utils.get_item_properties(
s, columns,
- formatters={'Extra Specs': utils.format_dict,
- 'id': _format_encryption_info},
+ formatters=formatters,
) for s in data))
@@ -490,7 +522,7 @@ class ShowVolumeType(command.ShowOne):
volume_client = self.app.client_manager.volume
volume_type = utils.find_resource(
volume_client.volume_types, parsed_args.volume_type)
- properties = utils.format_dict(
+ properties = format_columns.DictColumn(
volume_type._info.pop('extra_specs', {}))
volume_type._info.update({'properties': properties})
access_project_ids = None
@@ -502,7 +534,7 @@ class ShowVolumeType(command.ShowOne):
for item in volume_type_access]
# TODO(Rui Chen): This format list case can be removed after
# patch https://review.opendev.org/#/c/330223/ merged.
- access_project_ids = utils.format_list(project_ids)
+ access_project_ids = format_columns.ListColumn(project_ids)
except Exception as e:
msg = _('Failed to get access project list for volume type '
'%(type)s: %(e)s')
@@ -515,7 +547,8 @@ class ShowVolumeType(command.ShowOne):
volume_type.id)
encryption._info.pop("volume_type_id", None)
volume_type._info.update(
- {'encryption': utils.format_dict(encryption._info)})
+ {'encryption':
+ format_columns.DictColumn(encryption._info)})
except Exception as e:
LOG.error(_("Failed to display the encryption information "
"of this volume type: %s"), e)