diff --git a/doc/source/command-objects/security-group-rule.rst b/doc/source/command-objects/security-group-rule.rst index ce2e4d346..ec03644e9 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 a514085b0..42581d557 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 cfe3d46e5..0e7ee05d8 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))