Use raw values when non-table formatter is used
neutron CLI supports various output formats such as json, yaml (e.g. neutron net-list -f json), but the current output formattings is optimized to the table formatter to get human-friendly output in normal CLI use (For example, new lines are inserted). However, this kind of formatting is unnecessary when other output formatters are used and prevents users from getting proper data. This commit changes to skip format_output_data() method when output formatters other than 'table' are used. Now we have proper outputs in JSON, YAML or other formats. In CreateCommand and ShowCommand, cleanup_output_data() is moved to each command class because it should be called regardless of a formatter type. In ListCommand, value formatter for CSV is still supported for backward compatiblity, but the value formatter for fixed_ips of the port resource is removed because it brings no much value in CSV output. Closes-Bug: #1524624 Change-Id: I2668fa90402d7119db69f09a20fb7c7270c9616e
This commit is contained in:
parent
8460b0dbb3
commit
7bf8f229bb
|
@ -429,7 +429,6 @@ class NeutronCommand(command.Command):
|
|||
pass
|
||||
|
||||
def format_output_data(self, data):
|
||||
self.cleanup_output_data(data)
|
||||
# Modify data to make it more readable
|
||||
if self.resource in data:
|
||||
for k, v in six.iteritems(data[self.resource]):
|
||||
|
@ -484,7 +483,9 @@ class CreateCommand(NeutronCommand, show.ShowOne):
|
|||
data = obj_creator(self.parent_id, body)
|
||||
else:
|
||||
data = obj_creator(body)
|
||||
self.format_output_data(data)
|
||||
self.cleanup_output_data(data)
|
||||
if parsed_args.formatter == 'table':
|
||||
self.format_output_data(data)
|
||||
info = self.resource in data and data[self.resource] or None
|
||||
if info:
|
||||
if parsed_args.formatter == 'table':
|
||||
|
@ -754,9 +755,14 @@ class ListCommand(NeutronCommand, lister.Lister):
|
|||
# Also Keep their order the same as in list_columns
|
||||
_columns = [x for x in self.list_columns if x in _columns]
|
||||
|
||||
formatters = self._formatters
|
||||
if hasattr(self, '_formatters_csv') and parsed_args.formatter == 'csv':
|
||||
if parsed_args.formatter == 'table':
|
||||
formatters = self._formatters
|
||||
elif (parsed_args.formatter == 'csv'
|
||||
and hasattr(self, '_formatters_csv')):
|
||||
formatters = self._formatters_csv
|
||||
else:
|
||||
# For other formatters, we use raw value returned from neutron
|
||||
formatters = {}
|
||||
|
||||
return (_columns, (utils.get_item_properties(
|
||||
s, _columns, formatters=formatters, )
|
||||
|
@ -814,7 +820,9 @@ class ShowCommand(NeutronCommand, show.ShowOne):
|
|||
data = obj_shower(_id, self.parent_id, **params)
|
||||
else:
|
||||
data = obj_shower(_id, **params)
|
||||
self.format_output_data(data)
|
||||
self.cleanup_output_data(data)
|
||||
if parsed_args.formatter == 'table':
|
||||
self.format_output_data(data)
|
||||
resource = data[self.resource]
|
||||
if self.resource in data:
|
||||
return zip(*sorted(six.iteritems(resource)))
|
||||
|
|
|
@ -33,13 +33,6 @@ def _format_fixed_ips(port):
|
|||
return ''
|
||||
|
||||
|
||||
def _format_fixed_ips_csv(port):
|
||||
try:
|
||||
return jsonutils.dumps(port['fixed_ips'])
|
||||
except (TypeError, KeyError):
|
||||
return ''
|
||||
|
||||
|
||||
def _add_updatable_args(parser):
|
||||
parser.add_argument(
|
||||
'--name',
|
||||
|
@ -90,7 +83,6 @@ class ListPort(neutronV20.ListCommand):
|
|||
|
||||
resource = 'port'
|
||||
_formatters = {'fixed_ips': _format_fixed_ips, }
|
||||
_formatters_csv = {'fixed_ips': _format_fixed_ips_csv, }
|
||||
list_columns = ['id', 'name', 'mac_address', 'fixed_ips']
|
||||
pagination_support = True
|
||||
sorting_support = True
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
import contextlib
|
||||
import itertools
|
||||
import json
|
||||
import sys
|
||||
|
||||
import fixtures
|
||||
|
@ -25,11 +26,13 @@ from oslotest import base
|
|||
import requests
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
import yaml
|
||||
|
||||
from neutronclient.common import constants
|
||||
from neutronclient.common import exceptions
|
||||
from neutronclient.common import utils
|
||||
from neutronclient.neutron import v2_0 as neutronV2_0
|
||||
from neutronclient.neutron.v2_0 import network
|
||||
from neutronclient import shell
|
||||
from neutronclient.v2_0 import client
|
||||
|
||||
|
@ -1020,3 +1023,86 @@ class GeneratorWithMetaTest(base.BaseTestCase):
|
|||
|
||||
self.assertTrue(hasattr(obj, 'request_ids'))
|
||||
self.assertEqual([REQUEST_ID], obj.request_ids)
|
||||
|
||||
|
||||
class CLITestV20OutputFormatter(CLITestV20Base):
|
||||
|
||||
def _test_create_resource_with_formatter(self, fmt):
|
||||
resource = 'network'
|
||||
cmd = network.CreateNetwork(MyApp(sys.stdout), None)
|
||||
args = ['-f', fmt, 'myname']
|
||||
position_names = ['name']
|
||||
position_values = ['myname']
|
||||
self._test_create_resource(resource, cmd, 'myname', 'myid', args,
|
||||
position_names, position_values)
|
||||
|
||||
def test_create_resource_table(self):
|
||||
self._test_create_resource_with_formatter('table')
|
||||
print(self.fake_stdout.content)
|
||||
# table data is contains in the third element.
|
||||
data = self.fake_stdout.content[2].split('\n')
|
||||
self.assertTrue(any(' id ' in d for d in data))
|
||||
self.assertTrue(any(' name ' in d for d in data))
|
||||
|
||||
def test_create_resource_json(self):
|
||||
self._test_create_resource_with_formatter('json')
|
||||
data = json.loads(self.fake_stdout.make_string())
|
||||
self.assertEqual('myname', data['name'])
|
||||
self.assertEqual('myid', data['id'])
|
||||
|
||||
def test_create_resource_yaml(self):
|
||||
self._test_create_resource_with_formatter('yaml')
|
||||
data = yaml.load(self.fake_stdout.make_string())
|
||||
self.assertEqual('myname', data['name'])
|
||||
self.assertEqual('myid', data['id'])
|
||||
|
||||
def _test_show_resource_with_formatter(self, fmt):
|
||||
resource = 'network'
|
||||
cmd = network.ShowNetwork(MyApp(sys.stdout), None)
|
||||
args = ['-f', fmt, '-F', 'id', '-F', 'name', 'myid']
|
||||
self._test_show_resource(resource, cmd, 'myid',
|
||||
args, ['id', 'name'])
|
||||
|
||||
def test_show_resource_table(self):
|
||||
self._test_show_resource_with_formatter('table')
|
||||
data = self.fake_stdout.content[0].split('\n')
|
||||
self.assertTrue(any(' id ' in d for d in data))
|
||||
self.assertTrue(any(' name ' in d for d in data))
|
||||
|
||||
def test_show_resource_json(self):
|
||||
self._test_show_resource_with_formatter('json')
|
||||
data = json.loads(''.join(self.fake_stdout.content))
|
||||
self.assertEqual('myname', data['name'])
|
||||
self.assertEqual('myid', data['id'])
|
||||
|
||||
def test_show_resource_yaml(self):
|
||||
self._test_show_resource_with_formatter('yaml')
|
||||
data = yaml.load(''.join(self.fake_stdout.content))
|
||||
self.assertEqual('myname', data['name'])
|
||||
self.assertEqual('myid', data['id'])
|
||||
|
||||
def _test_list_resources_with_formatter(self, fmt):
|
||||
resources = 'networks'
|
||||
cmd = network.ListNetwork(MyApp(sys.stdout), None)
|
||||
# ListNetwork has its own extend_list, so we need to stub out it
|
||||
# to avoid an extra API call.
|
||||
self.mox.StubOutWithMock(network.ListNetwork, "extend_list")
|
||||
network.ListNetwork.extend_list(mox.IsA(list), mox.IgnoreArg())
|
||||
self._test_list_resources(resources, cmd, output_format=fmt)
|
||||
|
||||
def test_list_resources_table(self):
|
||||
self._test_list_resources_with_formatter('table')
|
||||
data = self.fake_stdout.content[0].split('\n')
|
||||
self.assertTrue(any(' id ' in d for d in data))
|
||||
self.assertTrue(any(' myid1 ' in d for d in data))
|
||||
self.assertTrue(any(' myid2 ' in d for d in data))
|
||||
|
||||
def test_list_resources_json(self):
|
||||
self._test_list_resources_with_formatter('json')
|
||||
data = json.loads(''.join(self.fake_stdout.content))
|
||||
self.assertEqual(['myid1', 'myid2'], [d['id'] for d in data])
|
||||
|
||||
def test_list_resources_yaml(self):
|
||||
self._test_list_resources_with_formatter('yaml')
|
||||
data = yaml.load(''.join(self.fake_stdout.content))
|
||||
self.assertEqual(['myid1', 'myid2'], [d['id'] for d in data])
|
||||
|
|
Loading…
Reference in New Issue