diff --git a/doc/source/command-objects/security-group-rule.rst b/doc/source/command-objects/security-group-rule.rst index 5284b2dc22..69869dc15e 100644 --- a/doc/source/command-objects/security-group-rule.rst +++ b/doc/source/command-objects/security-group-rule.rst @@ -126,6 +126,8 @@ List security group rules os security group rule list [--all-projects] + [--protocol ] + [--ingress | --egress] [--long] [] @@ -142,6 +144,28 @@ List security group rules *Compute version 2 does not have additional fields to display.* + +.. option:: --protocol + + List rules by the IP protocol (ah, dhcp, egp, esp, gre, icmp, igmp, + ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt,ipv6-opts, ipv6-route, + ospf, pgm, rsvp, sctp, tcp, udp, udplite, vrrp and integer + representations [0-255]) + + *Network version 2* + +.. option:: --ingress + + List rules applied to incoming network traffic + + *Network version 2 only* + +.. option:: --egress + + List rules applied to outgoing network traffic + + *Network version 2 only* + .. describe:: List all rules in this security group (name or ID) diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py index e3be44ece7..3b9055df9c 100644 --- a/openstackclient/network/v2/security_group_rule.py +++ b/openstackclient/network/v2/security_group_rule.py @@ -379,6 +379,28 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister): default=False, help=argparse.SUPPRESS ) + parser.add_argument( + '--protocol', + metavar='', + type=_convert_to_lowercase, + help=_("List rules by the IP protocol (" + "ah, dhcp, egp, esp, gre, icmp, igmp, " + "ipv6-encap, ipv6-frag, ipv6-icmp, ipv6-nonxt, " + "ipv6-opts, ipv6-route, ospf, pgm, rsvp, sctp, tcp, " + "udp, udplite, vrrp and integer representations [0-255])." + ) + ) + direction_group = parser.add_mutually_exclusive_group() + direction_group.add_argument( + '--ingress', + action='store_true', + help=_("List rules applied to incoming network traffic") + ) + direction_group.add_argument( + '--egress', + action='store_true', + help=_("List rules applied to outgoing network traffic") + ) parser.add_argument( '--long', action='store_true', @@ -443,6 +465,14 @@ class ListSecurityGroupRule(common.NetworkAndComputeLister): query = {'security_group_id': security_group_id} else: columns = columns + ('security_group_id',) + + if parsed_args.ingress: + query['direction'] = 'ingress' + if parsed_args.egress: + query['direction'] = 'egress' + if parsed_args.protocol is not None: + query['protocol'] = parsed_args.protocol + rules = list(client.security_group_rules(**query)) # Reformat the rules to display a port range instead diff --git a/openstackclient/tests/unit/network/v2/test_security_group_rule.py b/openstackclient/tests/unit/network/v2/test_security_group_rule.py index 96d58e5c00..f91314d667 100644 --- a/openstackclient/tests/unit/network/v2/test_security_group_rule.py +++ b/openstackclient/tests/unit/network/v2/test_security_group_rule.py @@ -942,6 +942,60 @@ class TestListSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): self.assertEqual(self.expected_columns_no_group, columns) self.assertEqual(self.expected_data_no_group, list(data)) + def test_list_with_protocol(self): + self._security_group_rule_tcp.port_range_min = 80 + arglist = [ + '--protocol', 'tcp', + ] + verifylist = [ + ('protocol', 'tcp'), + ] + 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(**{ + 'protocol': 'tcp', + }) + self.assertEqual(self.expected_columns_no_group, columns) + self.assertEqual(self.expected_data_no_group, list(data)) + + def test_list_with_ingress(self): + self._security_group_rule_tcp.port_range_min = 80 + arglist = [ + '--ingress', + ] + verifylist = [ + ('ingress', 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(**{ + 'direction': 'ingress', + }) + self.assertEqual(self.expected_columns_no_group, columns) + self.assertEqual(self.expected_data_no_group, list(data)) + + def test_list_with_wrong_egress(self): + self._security_group_rule_tcp.port_range_min = 80 + arglist = [ + '--egress', + ] + verifylist = [ + ('egress', 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(**{ + 'direction': 'egress', + }) + self.assertEqual(self.expected_columns_no_group, columns) + self.assertEqual(self.expected_data_no_group, list(data)) + class TestListSecurityGroupRuleCompute(TestSecurityGroupRuleCompute): diff --git a/releasenotes/notes/bug-1613533-93279179c6f70117.yaml b/releasenotes/notes/bug-1613533-93279179c6f70117.yaml new file mode 100644 index 0000000000..8907041a56 --- /dev/null +++ b/releasenotes/notes/bug-1613533-93279179c6f70117.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Add ``--ingress``, ``--egress`` and ``--protocol`` options to + ``security group rule list`` command. + [Bug `1613533 `_] \ No newline at end of file