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:
parent
e3a6fc27b0
commit
94c9cd5c66
@ -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)
|
||||
|
@ -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
|
||||
------------------
|
||||
|
@ -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.
|
||||
|
@ -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):
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user