From 96cc5eb3540e4753a8862020b2f6e78a465be4e2 Mon Sep 17 00:00:00 2001 From: Richard Theis Date: Wed, 16 Dec 2015 16:01:40 -0600 Subject: [PATCH] Add support to list all security group rules Both nova and neutron allow security group rules to be listed without specifying the owning security group. This patch set makes the group argument on 'os security group rule list' optional. Behavior is unchanged when the argument is specified. When the argument is not specified then all accessible security group rules will be listed. The listing will include the owning security group for each rule. Change-Id: I6914baecf70a65354e1e82dad92c6afbd32b4973 Related-Bug: #1519512 --- .../command-objects/security-group-rule.rst | 2 +- openstackclient/compute/v2/security_group.py | 36 +++++--- .../compute/v2/test_security_group_rule.py | 88 +++++++++++++++++-- 3 files changed, 107 insertions(+), 19 deletions(-) diff --git a/doc/source/command-objects/security-group-rule.rst b/doc/source/command-objects/security-group-rule.rst index ce2e4d346f..ec03644e9f 100644 --- a/doc/source/command-objects/security-group-rule.rst +++ b/doc/source/command-objects/security-group-rule.rst @@ -62,7 +62,7 @@ List security group rules .. code:: bash os security group rule list - + [] .. describe:: diff --git a/openstackclient/compute/v2/security_group.py b/openstackclient/compute/v2/security_group.py index a514085b08..42581d5578 100644 --- a/openstackclient/compute/v2/security_group.py +++ b/openstackclient/compute/v2/security_group.py @@ -278,6 +278,7 @@ class ListSecurityGroupRule(lister.Lister): parser.add_argument( 'group', metavar='', + nargs='?', help='List all rules in this security group (name or ID)', ) return parser @@ -286,19 +287,6 @@ class ListSecurityGroupRule(lister.Lister): self.log.debug("take_action(%s)", parsed_args) compute_client = self.app.client_manager.compute - group = utils.find_resource( - compute_client.security_groups, - parsed_args.group, - ) - - # Argh, the rules are not Resources... - rules = [] - for rule in group.rules: - rules.append(security_group_rules.SecurityGroupRule( - compute_client.security_group_rules, - _xform_security_group_rule(rule), - )) - columns = column_headers = ( "ID", "IP Protocol", @@ -306,6 +294,28 @@ class ListSecurityGroupRule(lister.Lister): "Port Range", "Remote Security Group", ) + + rules_to_list = [] + if parsed_args.group: + group = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + rules_to_list = group.rules + else: + columns = columns + ('parent_group_id',) + column_headers = column_headers + ('Security Group',) + for group in compute_client.security_groups.list(): + rules_to_list.extend(group.rules) + + # Argh, the rules are not Resources... + rules = [] + for rule in rules_to_list: + rules.append(security_group_rules.SecurityGroupRule( + compute_client.security_group_rules, + _xform_security_group_rule(rule), + )) + return (column_headers, (utils.get_item_properties( s, columns, diff --git a/openstackclient/tests/compute/v2/test_security_group_rule.py b/openstackclient/tests/compute/v2/test_security_group_rule.py index cfe3d46e59..0e7ee05d87 100644 --- a/openstackclient/tests/compute/v2/test_security_group_rule.py +++ b/openstackclient/tests/compute/v2/test_security_group_rule.py @@ -68,6 +68,28 @@ SECURITY_GROUP = { SECURITY_GROUP_RULE_REMOTE_GROUP], } +security_group_2_id = '12' +security_group_2_name = 'he-shoots' +security_group_2_description = 'he scores' + +SECURITY_GROUP_2_RULE = { + 'id': '2', + 'group': {}, + 'ip_protocol': 'tcp', + 'ip_range': {}, + 'parent_group_id': security_group_2_id, + 'from_port': 80, + 'to_port': 80, +} + +SECURITY_GROUP_2 = { + 'id': security_group_2_id, + 'name': security_group_2_name, + 'description': security_group_2_description, + 'tenant_id': identity_fakes.project_id, + 'rules': [SECURITY_GROUP_2_RULE], +} + class FakeSecurityGroupRuleResource(fakes.FakeResource): @@ -383,12 +405,22 @@ class TestSecurityGroupRuleList(TestSecurityGroupRule): def setUp(self): super(TestSecurityGroupRuleList, self).setUp() - self.secgroups_mock.get.return_value = FakeSecurityGroupRuleResource( + security_group_mock = FakeSecurityGroupRuleResource( None, copy.deepcopy(SECURITY_GROUP), loaded=True, ) + security_group_2_mock = FakeSecurityGroupRuleResource( + None, + copy.deepcopy(SECURITY_GROUP_2), + loaded=True, + ) + + self.secgroups_mock.get.return_value = security_group_mock + self.secgroups_mock.list.return_value = [security_group_mock, + security_group_2_mock] + # Get the command object to test self.cmd = security_group.ListSecurityGroupRule(self.app, None) @@ -420,18 +452,64 @@ class TestSecurityGroupRuleList(TestSecurityGroupRule): security_group_rule_cidr, '0:0', '', - ), ( + ), ( security_group_rule_id, 'icmp', security_group_rule_cidr, '', '', - ), ( + ), ( security_group_rule_id, 'tcp', '', '80:80', 'default', - ), - ) + ),) + self.assertEqual(datalist, tuple(data)) + + def test_security_group_rule_list_no_group(self): + + parsed_args = self.check_parser(self.cmd, [], []) + + # DisplayCommandBase.take_action() returns two tuples + columns, data = self.cmd.take_action(parsed_args) + + collist = ( + 'ID', + 'IP Protocol', + 'IP Range', + 'Port Range', + 'Remote Security Group', + 'Security Group', + ) + self.assertEqual(collist, columns) + datalist = (( + security_group_rule_id, + 'tcp', + security_group_rule_cidr, + '0:0', + '', + security_group_id, + ), ( + security_group_rule_id, + 'icmp', + security_group_rule_cidr, + '', + '', + security_group_id, + ), ( + security_group_rule_id, + 'tcp', + '', + '80:80', + 'default', + security_group_id, + ), ( + '2', + 'tcp', + '', + '80:80', + '', + security_group_2_id, + ),) self.assertEqual(datalist, tuple(data))