Merge "Support pagination and filtering for job list operations"

This commit is contained in:
Zuul 2017-10-19 02:27:30 +00:00 committed by Gerrit Code Review
commit 4bf13ec7e2
9 changed files with 257 additions and 100 deletions

View File

@ -44,9 +44,9 @@ job_resource_map = {
# listed by alphabet order. # listed by alphabet order.
COLUMNS = ('id', 'project_id', 'status', 'timestamp', 'type') COLUMNS = ('id', 'project_id', 'status', 'timestamp', 'type')
# column headers that show in command line. # column headers about job that show in command line.
COLUMNS_REMAP = {'id': 'Id', COLUMNS_REMAP = {'id': 'ID',
'project_id': 'Project id', 'project_id': 'Project',
'timestamp': 'Timestamp', 'timestamp': 'Timestamp',
'status': 'Status', 'status': 'Status',
'type': 'Type'} 'type': 'Type'}

View File

@ -67,7 +67,7 @@ class TestShowJob(_TestJobCommand, utils.TestCommandWithoutOptions):
_job['job']['id'], _job['job']['id'],
] ]
verifylist = [ verifylist = [
('id', _job['job']['id']), ('job', _job['job']['id']),
] ]
self.job_manager.get = mock.Mock(return_value=_job) self.job_manager.get = mock.Mock(return_value=_job)
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -88,7 +88,6 @@ class TestListJob(_TestJobCommand):
self.job_manager.list = mock.Mock(return_value={'jobs': _jobs}) self.job_manager.list = mock.Mock(return_value={'jobs': _jobs})
parsed_args = self.check_parser(self.cmd) parsed_args = self.check_parser(self.cmd)
columns, data = (self.cmd.take_action(parsed_args)) columns, data = (self.cmd.take_action(parsed_args))
self.assertEqual(sorted(constants.COLUMNS_REMAP.values()), self.assertEqual(sorted(constants.COLUMNS_REMAP.values()),
sorted(columns)) sorted(columns))
self.assertEqual(len(_jobs), len(data)) self.assertEqual(len(_jobs), len(data))
@ -96,6 +95,96 @@ class TestListJob(_TestJobCommand):
sorted([tuple(o[k] for k in constants.COLUMNS) for o in _jobs]), sorted([tuple(o[k] for k in constants.COLUMNS) for o in _jobs]),
sorted(data)) sorted(data))
def test_list_with_filters(self):
_job = utils.FakeJob.create_single_job()
_job = _job['job']
# we filter the jobs by the following fields: project ID, type, status.
# given values of _job, then only single item _job is retrieved.
arglist = [
'--project-id', _job['project_id'],
'--type', _job['type'],
'--status', _job['status'],
]
verifylist = [
('project_id', _job['project_id']),
('type', _job['type']),
('status', _job['status'].lower()),
]
self.job_manager.list = mock.Mock(return_value={'jobs': [_job]})
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.assertEqual(1, len(data))
self.assertEqual(sorted(constants.COLUMNS_REMAP.values()),
sorted(columns))
# lower case of job status
arglist = [
'--status', _job['status'].lower(),
]
verifylist = [
('status', _job['status'].lower()),
]
self.job_manager.list = mock.Mock(return_value={'jobs': [_job]})
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.assertEqual(1, len(data))
self.assertEqual(sorted(constants.COLUMNS_REMAP.values()),
sorted(columns))
def test_invalid_job_status_filter(self):
# unrecognizable job status filter
arglist = [
'--status', 'new_1',
]
verifylist = []
self.assertRaises(utils.ParserException, self.check_parser,
self.cmd, arglist, verifylist)
def test_list_with_pagination(self):
number_of_jobs = 4
limit = number_of_jobs - 2
_jobs = utils.FakeJob.create_multiple_jobs(count=number_of_jobs)
# test list operation with pagination
arglist = [
'--limit', str(limit),
]
verifylist = [
('limit', limit),
]
self.job_manager.list = mock.Mock(return_value={"jobs": _jobs[:limit]})
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.assertEqual(limit, len(data))
self.assertEqual(sorted(constants.COLUMNS_REMAP.values()),
sorted(columns))
# test list operation with pagination and marker
arglist = [
'--limit', str(limit),
'--marker', _jobs[0]['id'],
]
verifylist = [
('limit', limit),
('marker', _jobs[0]['id']),
]
self.job_manager.list = mock.Mock(
return_value={"jobs": _jobs[1:limit+1]})
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args))
self.assertEqual(limit, len(data))
self.assertEqual(sorted(constants.COLUMNS_REMAP.values()),
sorted(columns))
class TestDeleteJob(_TestJobCommand, utils.TestCommandWithoutOptions): class TestDeleteJob(_TestJobCommand, utils.TestCommandWithoutOptions):
@ -109,7 +198,7 @@ class TestDeleteJob(_TestJobCommand, utils.TestCommandWithoutOptions):
_job['job']['id'], _job['job']['id'],
] ]
verifylist = [ verifylist = [
('id', _job['job']['id']), ('job', [_job['job']['id']]),
] ]
self.job_manager.delete = mock.Mock(return_value=None) self.job_manager.delete = mock.Mock(return_value=None)
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -130,7 +219,7 @@ class TestRedoJob(_TestJobCommand, utils.TestCommandWithoutOptions):
_job['job']['id'], _job['job']['id'],
] ]
verifylist = [ verifylist = [
('id', _job['job']['id']), ('job', _job['job']['id']),
] ]
self.job_manager.update = mock.Mock(return_value=None) self.job_manager.update = mock.Mock(return_value=None)
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)

View File

@ -126,8 +126,8 @@ class TestShowPod(_TestPodCommand, utils.TestCommandWithoutOptions):
class TestListPod(_TestPodCommand): class TestListPod(_TestPodCommand):
columns = [ columns = [
'Id', 'ID',
'Region name', 'Region Name',
] ]
def setUp(self): def setUp(self):

View File

@ -79,10 +79,10 @@ class TestShowRouting(_TestRoutingCommand, utils.TestCommandWithoutOptions):
class TestListRouting(_TestRoutingCommand): class TestListRouting(_TestRoutingCommand):
columns = [ columns = [
'Id', 'ID',
'Pod id', 'Pod ID',
'Resource type', 'Resource Type',
'Top id' 'Top ID'
] ]
def setUp(self): def setUp(self):
@ -100,8 +100,7 @@ class TestListRouting(_TestRoutingCommand):
return_value={'routings': _routings}) return_value={'routings': _routings})
parsed_args = self.check_parser(self.cmd) parsed_args = self.check_parser(self.cmd)
columns, data = (self.cmd.take_action(parsed_args)) columns, data = (self.cmd.take_action(parsed_args))
self.assertEqual(sorted(self.columns), sorted(columns))
self.assertEqual(self.columns, sorted(columns))
self.assertEqual(len(_routings), len(data)) self.assertEqual(len(_routings), len(data))
def test_list_with_filters(self): def test_list_with_filters(self):
@ -151,7 +150,7 @@ class TestListRouting(_TestRoutingCommand):
def test_list_with_pagination(self): def test_list_with_pagination(self):
_routings = utils.FakeRouting.create_multiple_routings(count=3) _routings = utils.FakeRouting.create_multiple_routings(count=3)
arglist = [ arglist = [
'--page-size', '2', '--limit', '2',
'--marker', _routings[0]['id'], '--marker', _routings[0]['id'],
] ]
verifylist = [ verifylist = [
@ -167,7 +166,7 @@ class TestListRouting(_TestRoutingCommand):
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = (self.cmd.take_action(parsed_args)) columns, data = (self.cmd.take_action(parsed_args))
self.assertEqual(self.columns, sorted(columns)) self.assertEqual(sorted(self.columns), sorted(columns))
self.assertEqual(2, len(data)) self.assertEqual(2, len(data))
@ -178,12 +177,14 @@ class TestDeleteRouting(_TestRoutingCommand, utils.TestCommandWithoutOptions):
self.cmd = routings_cli.DeleteRouting(self.app, None) self.cmd = routings_cli.DeleteRouting(self.app, None)
def test_delete_routing(self): def test_delete_routing(self):
_routing = utils.FakeRouting.create_single_routing() _routings = utils.FakeRouting.create_multiple_routings(count=2)
arglist = [ arglist = [
_routing['routing']['id'], _routings[0]['id'],
_routings[1]['id'],
] ]
verifylist = [ verifylist = [
('routing', [_routing['routing']['id']]), ('routing', [_routings[0]['id'], _routings[1]['id']]),
] ]
self.routing_manager.delete = mock.Mock(return_value=None) self.routing_manager.delete = mock.Mock(return_value=None)
parsed_args = self.check_parser(self.cmd, arglist, verifylist) parsed_args = self.check_parser(self.cmd, arglist, verifylist)

View File

@ -17,7 +17,7 @@ def prepare_column_headers(columns, remap=None):
for c in columns: for c in columns:
for old, new in remap.items(): for old, new in remap.items():
c = c.replace(old, new) c = c.replace(old, new)
new_columns.append(c.replace('_', ' ').capitalize()) new_columns.append(c.replace('_', ' '))
return new_columns return new_columns

View File

@ -18,10 +18,10 @@ from tricircleclient.v1 import base
class JobManager(base.Manager): class JobManager(base.Manager):
def list(self, search_opts=None): def list(self, path):
"""Get a list of jobs.""" """Get a list of jobs."""
return self._get( return self._get(
'/jobs', path,
headers={'Content-Type': "application/json"}).json() headers={'Content-Type': "application/json"}).json()
def create(self, job): def create(self, job):

View File

@ -13,6 +13,7 @@
from osc_lib.command import command from osc_lib.command import command
from oslo_log import log as logging from oslo_log import log as logging
from six.moves.urllib import parse
from tricircleclient import constants from tricircleclient import constants
from tricircleclient import utils from tricircleclient import utils
@ -33,6 +34,59 @@ def _job_from_args(parsed_args):
return {'job': data} return {'job': data}
def _add_pagination_argument(parser):
parser.add_argument(
'--limit',
dest='limit', metavar="<num-jobs>", type=int,
help="Maximum number of jobs to return",
default=None)
def _add_marker_argument(parser):
parser.add_argument(
'--marker',
dest='marker', metavar="<job>", type=str,
help="ID of last job in previous page, jobs after marker will be "
"returned. Display all jobs if not specified.",
default=None)
def _add_filtering_arguments(parser):
# available filtering fields: project ID, type, status
parser.add_argument(
'--project-id',
dest='project_id', metavar="<project-id>", type=str,
help="ID of a project object in Keystone",
default=None)
parser.add_argument(
'--type',
dest='type', metavar="<type>", type=str,
choices=constants.job_resource_map.keys(),
help="Job type",
default=None)
parser.add_argument(
'--status',
dest='status', metavar="<status>", type=lambda str: str.lower(),
choices=['new', 'running', 'success', 'fail'],
help="Execution status of the job. It's case-insensitive",
default=None)
def _add_search_options(parsed_args):
search_opts = {}
for key in ('limit', 'marker', 'project_id', 'type', 'status'):
value = getattr(parsed_args, key, None)
if value is not None:
search_opts[key] = value
return search_opts
def _prepare_query_string(params):
"""Convert dict params to query string"""
params = sorted(params.items(), key=lambda x: x[0])
return '?%s' % parse.urlencode(params) if params else ''
def expand_job_resource(job): def expand_job_resource(job):
# because job['resource'] is a dict value, so we should # because job['resource'] is a dict value, so we should
# expand its values and let them show as other fields in the # expand its values and let them show as other fields in the
@ -47,10 +101,26 @@ class ListJobs(command.Lister):
"""List Jobs""" """List Jobs"""
log = logging.getLogger(__name__ + ".ListJobs") log = logging.getLogger(__name__ + ".ListJobs")
path = '/jobs'
def get_parser(self, prog_name):
parser = super(ListJobs, self).get_parser(prog_name)
_add_pagination_argument(parser)
_add_marker_argument(parser)
_add_filtering_arguments(parser)
return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args) self.log.debug("take_action(%s)" % parsed_args)
client = self.app.client_manager.multiregion_networking client = self.app.client_manager.multiregion_networking
data = client.job.list()
# add pagination/marker/filter to list operation
search_opts = _add_search_options(parsed_args)
self.path += _prepare_query_string(search_opts)
data = client.job.list(self.path)
column_headers = utils.prepare_column_headers(constants.COLUMNS, column_headers = utils.prepare_column_headers(constants.COLUMNS,
constants.COLUMNS_REMAP) constants.COLUMNS_REMAP)
return utils.list2cols(constants.COLUMNS, data['jobs'], column_headers) return utils.list2cols(constants.COLUMNS, data['jobs'], column_headers)
@ -75,44 +145,44 @@ class CreateJob(command.ShowOne):
) )
parser.add_argument( parser.add_argument(
'--project_id', '--project_id',
metavar="<project_id>", metavar="<project-id>",
required=True, required=True,
help="Uuid of a project object in Keystone", help="ID of a project object in Keystone",
) )
parser.add_argument( parser.add_argument(
'--router_id', '--router_id',
metavar="<router_id>", metavar="<router-id>",
help="Uuid of a router", help="ID of a router",
) )
parser.add_argument( parser.add_argument(
'--network_id', '--network_id',
metavar="<network_id>", metavar="<network-id>",
help="Uuid of a network", help="ID of a network",
) )
parser.add_argument( parser.add_argument(
'--pod_id', '--pod_id',
metavar="<pod_id>", metavar="<pod-id>",
help="Uuid of a pod", help="ID of a pod",
) )
parser.add_argument( parser.add_argument(
'--port_id', '--port_id',
metavar="<port_id>", metavar="<port-id>",
help="Uuid of a port", help="ID of a port",
) )
parser.add_argument( parser.add_argument(
'--trunk_id', '--trunk_id',
metavar="<trunk_id>", metavar="<trunk-id>",
help="Uuid of a trunk", help="ID of a trunk",
) )
parser.add_argument( parser.add_argument(
'--subnet_id', '--subnet_id',
metavar="<subnet_id>", metavar="<subnet-id>",
help="Uuid of a subnet", help="ID of a subnet",
) )
parser.add_argument( parser.add_argument(
'--portchain_id', '--portchain_id',
metavar="<portchain_id>", metavar="<portchain-id>",
help="Uuid of a port chain", help="ID of a port chain",
) )
return parser return parser
@ -132,16 +202,16 @@ class ShowJob(command.ShowOne):
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(ShowJob, self).get_parser(prog_name) parser = super(ShowJob, self).get_parser(prog_name)
parser.add_argument( parser.add_argument(
"id", "job",
metavar="<id>", metavar="<job>",
help="Uuid of the job to display", help="ID of the job to display",
) )
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args) self.log.debug("take_action(%s)" % parsed_args)
client = self.app.client_manager.multiregion_networking client = self.app.client_manager.multiregion_networking
data = client.job.get(parsed_args.id) data = client.job.get(parsed_args.job)
if 'job' in data.keys(): if 'job' in data.keys():
return self.dict2columns(expand_job_resource(data['job'])) return self.dict2columns(expand_job_resource(data['job']))
@ -155,16 +225,18 @@ class DeleteJob(command.Command):
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(DeleteJob, self).get_parser(prog_name) parser = super(DeleteJob, self).get_parser(prog_name)
parser.add_argument( parser.add_argument(
"id", "job",
metavar="<id>", metavar="<job>",
help="Uuid of the job to delete", nargs="+",
help="ID(s) of the job(s) to delete",
) )
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args) self.log.debug("take_action(%s)" % parsed_args)
client = self.app.client_manager.multiregion_networking client = self.app.client_manager.multiregion_networking
client.job.delete(parsed_args.id) for job_id in parsed_args.job:
client.job.delete(job_id)
class RedoJob(command.Command): class RedoJob(command.Command):
@ -176,13 +248,13 @@ class RedoJob(command.Command):
parser = super(RedoJob, self).get_parser(prog_name) parser = super(RedoJob, self).get_parser(prog_name)
parser.add_argument( parser.add_argument(
'id', 'job',
metavar="<id>", metavar="<job>",
help="Uuid of the job to redo", help="ID of the job to redo",
) )
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
self.log.debug("take_action(%s)" % parsed_args) self.log.debug("take_action(%s)" % parsed_args)
client = self.app.client_manager.multiregion_networking client = self.app.client_manager.multiregion_networking
client.job.update(parsed_args.id) client.job.update(parsed_args.job)

View File

@ -28,7 +28,7 @@ class ListPods(command.Lister):
self.log.debug("take_action(%s)" % parsed_args) self.log.debug("take_action(%s)" % parsed_args)
client = self.app.client_manager.multiregion_networking client = self.app.client_manager.multiregion_networking
data = client.pod.list() data = client.pod.list()
remap = {'pod_id': 'Id', remap = {'pod_id': 'ID',
'region_name': 'Region Name', 'region_name': 'Region Name',
'az_name': 'Availability Zone', 'az_name': 'Availability Zone',
'dc_name': 'Data Center'} 'dc_name': 'Data Center'}

View File

@ -33,50 +33,50 @@ def _routing_from_args(parsed_args):
def _add_pagination_argument(parser): def _add_pagination_argument(parser):
parser.add_argument( parser.add_argument(
'-P', '--page-size', '--limit',
dest='limit', metavar='SIZE', type=int, dest='limit', metavar="<num-routings>", type=int,
help="Maximum number of routings to return", help="Maximum number of routings to return",
default=None) default=None)
def _add_marker_argument(parser): def _add_marker_argument(parser):
parser.add_argument( parser.add_argument(
'-M', '--marker', '--marker',
dest='marker', metavar='MARKER', type=str, dest='marker', metavar="<routing>", type=str,
help="Starting point for next routing list " help="ID of last routing in previous page, routings after marker "
"that shares same routing id", "will be returned. Display all routings if not specified.",
default=None) default=None)
def _add_filtering_arguments(parser): def _add_filtering_arguments(parser):
parser.add_argument( parser.add_argument(
'--id', '--routing',
dest='id', metavar='id', type=int, dest='routing', metavar="<routing>", type=int,
help="Uuid of a routing", help="ID of a routing",
default=None) default=None)
parser.add_argument( parser.add_argument(
'--top-id', '--top-id',
dest='top_id', metavar='top_id', type=str, dest='top_id', metavar="<top-id>", type=str,
help="Resource id on Central Neutron", help="Resource id on Central Neutron",
default=None) default=None)
parser.add_argument( parser.add_argument(
'--bottom-id', '--bottom-id',
dest='bottom_id', metavar='bottom_id', type=str, dest='bottom_id', metavar="<bottom-id>", type=str,
help="Resource id on Local Neutron", help="Resource id on Local Neutron",
default=None) default=None)
parser.add_argument( parser.add_argument(
'--pod-id', '--pod-id',
dest='pod_id', metavar='pod_id', type=str, dest='pod_id', metavar="<pod-id>", type=str,
help="Uuid of a pod", help="ID of a pod",
default=None) default=None)
parser.add_argument( parser.add_argument(
'--project-id', '--project-id',
dest='project_id', metavar='project_id', type=str, dest='project_id', metavar="<project-id>", type=str,
help="Uuid of a project object in Keystone", help="ID of a project object in Keystone",
default=None) default=None)
parser.add_argument( parser.add_argument(
'--resource-type', '--resource-type',
dest='resource_type', metavar='resource_type', type=str, dest='resource_type', metavar="<resource-type>", type=str,
choices=['network', 'subnet', 'port', 'router', 'security_group', choices=['network', 'subnet', 'port', 'router', 'security_group',
'trunk', 'port_pair', 'port_pair_group', 'flow_classifier', 'trunk', 'port_pair', 'port_pair_group', 'flow_classifier',
'port_chain'], 'port_chain'],
@ -84,12 +84,12 @@ def _add_filtering_arguments(parser):
default=None) default=None)
parser.add_argument( parser.add_argument(
'--created-at', '--created-at',
dest='created_at', metavar='created_at', type=str, dest='created_at', metavar="<created-at>", type=str,
help="Create time of the resource routing", help="Create time of the resource routing",
default=None) default=None)
parser.add_argument( parser.add_argument(
'--updated-at', '--updated-at',
dest='updated_at', metavar='updated_at', type=str, dest='updated_at', metavar="<updated-at>", type=str,
help="Update time of the resource routing", help="Update time of the resource routing",
default=None) default=None)
@ -116,18 +116,13 @@ class ListRoutings(command.Lister):
COLS = ('id', 'pod_id', 'resource_type', 'top_id') COLS = ('id', 'pod_id', 'resource_type', 'top_id')
path = '/routings' path = '/routings'
pagination_support = True
marker_support = True
log = logging.getLogger(__name__ + ".ListRoutings") log = logging.getLogger(__name__ + ".ListRoutings")
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(ListRoutings, self).get_parser(prog_name) parser = super(ListRoutings, self).get_parser(prog_name)
if self.pagination_support: _add_pagination_argument(parser)
_add_pagination_argument(parser) _add_marker_argument(parser)
if self.marker_support:
_add_marker_argument(parser)
_add_filtering_arguments(parser) _add_filtering_arguments(parser)
return parser return parser
@ -141,13 +136,13 @@ class ListRoutings(command.Lister):
self.path += _prepare_query_string(search_opts) self.path += _prepare_query_string(search_opts)
data = client.routing.list(self.path) data = client.routing.list(self.path)
remap = {'id': 'Id', remap = {'resource_type': 'Resource Type',
'pod_id': 'Pod Id', 'pod': 'Pod',
'resource_type': 'Resource Type', 'id': 'ID',
'top_id': 'Top Id'} 'top': 'Top',
}
column_headers = utils.prepare_column_headers(self.COLS, column_headers = utils.prepare_column_headers(self.COLS,
remap) remap)
return utils.list2cols( return utils.list2cols(
self.COLS, data['routings'], column_headers) self.COLS, data['routings'], column_headers)
@ -162,31 +157,31 @@ class CreateRouting(command.ShowOne):
parser.add_argument( parser.add_argument(
'--top-id', '--top-id',
metavar="<top_id>", metavar="<top-id>",
required=True, required=True,
help="Resource id on Central Neutron", help="Resource id on Central Neutron",
) )
parser.add_argument( parser.add_argument(
'--bottom-id', '--bottom-id',
metavar="<bottom_id>", metavar="<bottom-id>",
required=True, required=True,
help="Resource id on Local Neutron", help="Resource id on Local Neutron",
) )
parser.add_argument( parser.add_argument(
'--pod-id', '--pod-id',
metavar="<pod_id>", metavar="<pod-id>",
required=True, required=True,
help="Uuid of a pod", help="ID of a pod",
) )
parser.add_argument( parser.add_argument(
'--project-id', '--project-id',
metavar="<project_id>", metavar="<project-id>",
required=True, required=True,
help="Uuid of a project object in Keystone", help="ID of a project object in Keystone",
) )
parser.add_argument( parser.add_argument(
'--resource-type', '--resource-type',
metavar="<resource_type>", metavar="<resource-type>",
choices=['network', 'subnet', 'port', 'router', 'security_group'], choices=['network', 'subnet', 'port', 'router', 'security_group'],
required=True, required=True,
help="Available resource types", help="Available resource types",
@ -211,7 +206,7 @@ class ShowRouting(command.ShowOne):
parser.add_argument( parser.add_argument(
"routing", "routing",
metavar="<routing>", metavar="<routing>",
help="Id of the routing resource to display", help="ID of the routing resource to display",
) )
return parser return parser
@ -234,7 +229,7 @@ class DeleteRouting(command.Command):
parser = super(DeleteRouting, self).get_parser(prog_name) parser = super(DeleteRouting, self).get_parser(prog_name)
parser.add_argument( parser.add_argument(
"routing", "routing",
metavar="<Routing>", metavar="<routing>",
nargs="+", nargs="+",
help="ID(s) of the routing resource(s) to delete", help="ID(s) of the routing resource(s) to delete",
) )
@ -258,33 +253,33 @@ class UpdateRouting(command.Command):
parser.add_argument( parser.add_argument(
'--top-id', '--top-id',
metavar="<top_id>", metavar="<top-id>",
help="Resource id on Central Neutron", help="Resource id on Central Neutron",
) )
parser.add_argument( parser.add_argument(
'--bottom-id', '--bottom-id',
metavar="<bottom_id>", metavar="<bottom-id>",
help="Resource id on Local Neutron", help="Resource id on Local Neutron",
) )
parser.add_argument( parser.add_argument(
'--pod-id', '--pod-id',
metavar="<pod_id>", metavar="<pod-id>",
help="Uuid of a pod", help="ID of a pod",
) )
parser.add_argument( parser.add_argument(
'--project-id', '--project-id',
metavar="<project_id>", metavar="<project-id>",
help="Uuid of a project object in Keystone", help="ID of a project object in Keystone",
) )
parser.add_argument( parser.add_argument(
'--resource-type', '--resource-type',
metavar="<resource_type>", metavar="<resource-type>",
choices=['network', 'subnet', 'port', 'router', 'security_group'], choices=['network', 'subnet', 'port', 'router', 'security_group'],
help="Available resource types", help="Available resource types",
) )
parser.add_argument( parser.add_argument(
"routing", "routing",
metavar="<Routing>", metavar="<routing>",
help="ID of the routing resource to update", help="ID of the routing resource to update",
) )
return parser return parser