Add options to security group rule list

Add the following options to the 'os security group rule list'
command:
  --long: Display direction and ethertype for Network v2
  --all-projects: Display information from all projects for Compute v2

Change-Id: If8a1cbd7669cdfa6577d6d2f6fffd9e999a39a82
Partial-Bug: #1519512
Implements: blueprint neutron-client
This commit is contained in:
Richard Theis 2016-04-11 13:45:12 -05:00
parent e3a6fc27b0
commit 94c9cd5c66
5 changed files with 149 additions and 23 deletions

View File

@ -98,8 +98,23 @@ List security group rules
.. code:: bash
os security group rule list
[--all-projects]
[--long]
[<group>]
.. option:: --all-projects
Display information from all projects (admin only)
*Network version 2 ignores this option and will always display information*
*for all projects (admin only).*
.. option:: --long
List additional fields in output
*Compute version 2 does not have additional fields to display.*
.. describe:: <group>
List all rules in this security group (name or ID)

View File

@ -69,7 +69,7 @@ List security groups
Display information from all projects (admin only)
*Network version 2 ignores this option and will always display information*
*for all projects.*
*for all projects (admin only).*
security group set
------------------

View File

@ -13,6 +13,7 @@
"""Security Group Rule action implementations"""
import argparse
import six
try:
@ -242,14 +243,50 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
)
return parser
def update_parser_network(self, parser):
# Accept but hide the argument for consistency with compute.
# Network will always return all projects for an admin.
parser.add_argument(
'--all-projects',
action='store_true',
default=False,
help=argparse.SUPPRESS
)
parser.add_argument(
'--long',
action='store_true',
default=False,
help=_("List additional fields in output")
)
return parser
def update_parser_compute(self, parser):
parser.add_argument(
'--all-projects',
action='store_true',
default=False,
help=_("Display information from all projects (admin only)")
)
# Accept but hide the argument for consistency with network.
# There are no additional fields to display at this time.
parser.add_argument(
'--long',
action='store_false',
default=False,
help=argparse.SUPPRESS
)
return parser
def _get_column_headers(self, parsed_args):
column_headers = (
'ID',
'IP Protocol',
'IP Range',
'Port Range',
'Remote Security Group',
)
if parsed_args.long:
column_headers = column_headers + ('Direction', 'Ethertype',)
column_headers = column_headers + ('Remote Security Group',)
if parsed_args.group is None:
column_headers = column_headers + ('Security Group',)
return column_headers
@ -261,8 +298,10 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
'protocol',
'remote_ip_prefix',
'port_range_min',
'remote_group_id',
)
if parsed_args.long:
columns = columns + ('direction', 'ethertype',)
columns = columns + ('remote_group_id',)
# Get the security group rules using the requested query.
query = {}
@ -309,7 +348,8 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister):
rules_to_list = group.rules
else:
columns = columns + ('parent_group_id',)
for group in client.security_groups.list():
search = {'all_tenants': parsed_args.all_projects}
for group in client.security_groups.list(search_opts=search):
rules_to_list.extend(group.rules)
# NOTE(rtheis): Turn the raw rules into resources.

View File

@ -532,31 +532,46 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
_security_group_rules = [_security_group_rule_tcp,
_security_group_rule_icmp]
expected_columns_with_group = (
expected_columns_with_group_and_long = (
'ID',
'IP Protocol',
'IP Range',
'Port Range',
'Direction',
'Ethertype',
'Remote Security Group',
)
expected_columns_no_group = (
'ID',
'IP Protocol',
'IP Range',
'Port Range',
'Remote Security Group',
'Security Group',
)
expected_columns_no_group = \
expected_columns_with_group + ('Security Group',)
expected_data_with_group = []
expected_data_with_group_and_long = []
expected_data_no_group = []
for _security_group_rule in _security_group_rules:
expected_rule_with_group = (
expected_data_with_group_and_long.append((
_security_group_rule.id,
_security_group_rule.protocol,
_security_group_rule.remote_ip_prefix,
security_group_rule._format_network_port_range(
_security_group_rule),
_security_group_rule.direction,
_security_group_rule.ethertype,
_security_group_rule.remote_group_id,
))
expected_data_no_group.append((
_security_group_rule.id,
_security_group_rule.protocol,
_security_group_rule.remote_ip_prefix,
security_group_rule._format_network_port_range(
_security_group_rule),
_security_group_rule.remote_group_id,
)
expected_rule_no_group = expected_rule_with_group + \
(_security_group_rule.security_group_id,)
expected_data_with_group.append(expected_rule_with_group)
expected_data_no_group.append(expected_rule_no_group)
_security_group_rule.security_group_id,
))
def setUp(self):
super(TestListSecurityGroupRuleNetwork, self).setUp()
@ -570,7 +585,7 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.cmd = security_group_rule.ListSecurityGroupRule(
self.app, self.namespace)
def test_list_no_group(self):
def test_list_default(self):
self._security_group_rule_tcp.port_range_min = 80
parsed_args = self.check_parser(self.cmd, [], [])
@ -580,12 +595,14 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.assertEqual(self.expected_columns_no_group, columns)
self.assertEqual(self.expected_data_no_group, list(data))
def test_list_with_group(self):
def test_list_with_group_and_long(self):
self._security_group_rule_tcp.port_range_min = 80
arglist = [
'--long',
self._security_group.id,
]
verifylist = [
('long', True),
('group', self._security_group.id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -595,8 +612,24 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):
self.network.security_group_rules.assert_called_once_with(**{
'security_group_id': self._security_group.id,
})
self.assertEqual(self.expected_columns_with_group, columns)
self.assertEqual(self.expected_data_with_group, list(data))
self.assertEqual(self.expected_columns_with_group_and_long, columns)
self.assertEqual(self.expected_data_with_group_and_long, list(data))
def test_list_with_ignored_options(self):
self._security_group_rule_tcp.port_range_min = 80
arglist = [
'--all-projects',
]
verifylist = [
('all_projects', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.network.security_group_rules.assert_called_once_with(**{})
self.assertEqual(self.expected_columns_no_group, columns)
self.assertEqual(self.expected_data_no_group, list(data))
class TestListSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
@ -665,11 +698,13 @@ class TestListSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
# Get the command object to test
self.cmd = security_group_rule.ListSecurityGroupRule(self.app, None)
def test_list_no_group(self):
def test_list_default(self):
parsed_args = self.check_parser(self.cmd, [], [])
columns, data = self.cmd.take_action(parsed_args)
self.compute.security_groups.list.assert_called_once_with()
self.compute.security_groups.list.assert_called_once_with(
search_opts={'all_tenants': False}
)
self.assertEqual(self.expected_columns_no_group, columns)
self.assertEqual(self.expected_data_no_group, list(data))
@ -689,6 +724,38 @@ class TestListSecurityGroupRuleCompute(TestSecurityGroupRuleCompute):
self.assertEqual(self.expected_columns_with_group, columns)
self.assertEqual(self.expected_data_with_group, list(data))
def test_list_all_projects(self):
arglist = [
'--all-projects',
]
verifylist = [
('all_projects', True),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.compute.security_groups.list.assert_called_once_with(
search_opts={'all_tenants': True}
)
self.assertEqual(self.expected_columns_no_group, columns)
self.assertEqual(self.expected_data_no_group, list(data))
def test_list_with_ignored_options(self):
arglist = [
'--long',
]
verifylist = [
('long', False),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.compute.security_groups.list.assert_called_once_with(
search_opts={'all_tenants': False}
)
self.assertEqual(self.expected_columns_no_group, columns)
self.assertEqual(self.expected_data_no_group, list(data))
class TestShowSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork):

View File

@ -2,9 +2,13 @@
features:
- The ``security group rule list`` command now uses Network v2
when enabled which results in ``egress`` security group rules
being displayed. In addition, security group rules for all
projects will be displayed when the ``group`` argument is not
specified (admin only).
being displayed. The ``--long`` option was also added for
Network v2 to display direction and ethertype information.
In addition, security group rules for all projects will be
displayed when the ``group`` argument is not specified
(admin only). This is done by default when using Network v2,
but requires the new ``--all-projects`` option when using
Compute v2.
[Bug `1519512 <https://bugs.launchpad.net/bugs/1519512>`_]
fixes:
- The ``security group rule list`` command no longer ignores