diff --git a/openstackclient/network/v2/security_group_rule.py b/openstackclient/network/v2/security_group_rule.py index 06d467254..ca0e00b9d 100644 --- a/openstackclient/network/v2/security_group_rule.py +++ b/openstackclient/network/v2/security_group_rule.py @@ -159,8 +159,8 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): help=_("IP protocol (ah, dccp, 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]; " - "default: tcp)") + "udp, udplite, vrrp and integer representations [0-255] " + "or any; default: tcp)") ) protocol_group.add_argument( '--proto', @@ -230,6 +230,8 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): protocol = parsed_args.protocol if parsed_args.proto is not None: protocol = parsed_args.proto + if protocol == 'any': + protocol = None return protocol def _is_ipv6_protocol(self, protocol): @@ -237,7 +239,7 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): # However, while the OSC CLI doesn't document the protocol, # the code must still handle it. In addition, handle both # protocol names and numbers. - if (protocol.startswith('ipv6-') or + if (protocol is not None and protocol.startswith('ipv6-') or protocol in ['icmpv6', '41', '43', '44', '58', '59', '60']): return True else: diff --git a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py index 36add8ca8..fe6d36492 100644 --- a/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py +++ b/openstackclient/tests/unit/network/v2/test_security_group_rule_network.py @@ -211,6 +211,36 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): self.assertEqual(self.expected_columns, columns) self.assertEqual(self.expected_data, data) + def test_create_protocol_any(self): + self._setup_security_group_rule({ + 'protocol': None, + 'remote_ip_prefix': '10.0.2.0/24', + }) + arglist = [ + '--proto', 'any', + '--src-ip', self._security_group_rule.remote_ip_prefix, + self._security_group.id, + ] + verifylist = [ + ('proto', 'any'), + ('protocol', None), + ('src_ip', self._security_group_rule.remote_ip_prefix), + ('group', self._security_group.id), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = self.cmd.take_action(parsed_args) + + self.network.create_security_group_rule.assert_called_once_with(**{ + 'direction': self._security_group_rule.direction, + 'ethertype': self._security_group_rule.ether_type, + 'protocol': self._security_group_rule.protocol, + 'remote_ip_prefix': self._security_group_rule.remote_ip_prefix, + 'security_group_id': self._security_group.id, + }) + self.assertEqual(self.expected_columns, columns) + self.assertEqual(self.expected_data, data) + def test_create_remote_group(self): self._setup_security_group_rule({ 'port_range_max': 22, diff --git a/releasenotes/notes/bug-1712242-934bbe2f2378f5bd.yaml b/releasenotes/notes/bug-1712242-934bbe2f2378f5bd.yaml new file mode 100644 index 000000000..322d0bd37 --- /dev/null +++ b/releasenotes/notes/bug-1712242-934bbe2f2378f5bd.yaml @@ -0,0 +1,12 @@ +--- +features: + - | + Add ``any`` as a ``--protocol`` option to ``security group rule create`` + command. + [Bug `1517134 `_] +fixes: + - | + It is now possible to create a security rule without specifying protocol + (using ``--protocol any``), which skips sending the protocol to the API + server entirely. Previously TCP was forced as default protocol when none + was specified.