diff --git a/doc/source/command-objects/security-group-rule.rst b/doc/source/command-objects/security-group-rule.rst index 9aa82cd30..2f212e5eb 100644 --- a/doc/source/command-objects/security-group-rule.rst +++ b/doc/source/command-objects/security-group-rule.rst @@ -18,6 +18,7 @@ Create a new security group rule [--dst-port ] [--ingress | --egress] [--ethertype ] + [--project [--project-domain ]] .. option:: --proto @@ -56,6 +57,19 @@ Create a new security group rule *Network version 2 only* +.. option:: --project + + Owner's project (name or ID) + + *Network version 2 only* + +.. option:: --project-domain + + Domain the project belongs to (name or ID). + This can be used in case collisions between project names exist. + + *Network version 2 only* + .. describe:: Create rule 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 832509143..509b19744 100644 --- a/openstackclient/network/v2/security_group_rule.py +++ b/openstackclient/network/v2/security_group_rule.py @@ -23,6 +23,7 @@ except ImportError: from openstackclient.common import exceptions from openstackclient.common import parseractions from openstackclient.common import utils +from openstackclient.identity import common as identity_common from openstackclient.network import common from openstackclient.network import utils as network_utils @@ -120,6 +121,12 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): help='Ethertype of network traffic ' '(IPv4, IPv6; default: IPv4)', ) + parser.add_argument( + '--project', + metavar='', + help="Owner's project (name or ID)" + ) + identity_common.add_project_domain_option_to_parser(parser) return parser def take_action_network(self, client, parsed_args): @@ -159,6 +166,14 @@ class CreateSecurityGroupRule(common.NetworkAndComputeShowOne): elif attrs['ethertype'] == 'IPv4': attrs['remote_ip_prefix'] = '0.0.0.0/0' attrs['security_group_id'] = security_group_id + if parsed_args.project is not None: + identity_client = self.app.client_manager.identity + project_id = identity_common.find_project( + identity_client, + parsed_args.project, + parsed_args.project_domain, + ).id + attrs['tenant_id'] = project_id # Create and show the security group rule. obj = client.create_security_group_rule(**attrs) diff --git a/openstackclient/tests/network/v2/test_security_group_rule.py b/openstackclient/tests/network/v2/test_security_group_rule.py index 9e9fd120d..c2fa12568 100644 --- a/openstackclient/tests/network/v2/test_security_group_rule.py +++ b/openstackclient/tests/network/v2/test_security_group_rule.py @@ -18,6 +18,7 @@ from openstackclient.network import utils as network_utils from openstackclient.network.v2 import security_group_rule from openstackclient.tests.compute.v2 import fakes as compute_fakes from openstackclient.tests import fakes +from openstackclient.tests.identity.v3 import fakes as identity_fakes from openstackclient.tests.network.v2 import fakes as network_fakes from openstackclient.tests import utils as tests_utils @@ -89,6 +90,30 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): self.network.find_security_group = mock.Mock( return_value=self._security_group) + # Set identity client v3. And get a shortcut to Identity client. + identity_client = identity_fakes.FakeIdentityv3Client( + endpoint=fakes.AUTH_URL, + token=fakes.AUTH_TOKEN, + ) + self.app.client_manager.identity = identity_client + self.identity = self.app.client_manager.identity + + # Get a shortcut to the ProjectManager Mock + self.projects_mock = self.identity.projects + self.projects_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.PROJECT), + loaded=True, + ) + + # Get a shortcut to the DomainManager Mock + self.domains_mock = self.identity.domains + self.domains_mock.get.return_value = fakes.FakeResource( + None, + copy.deepcopy(identity_fakes.DOMAIN), + loaded=True, + ) + # Get the command object to test self.cmd = security_group_rule.CreateSecurityGroupRule( self.app, self.namespace) @@ -231,6 +256,8 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): '--dst-port', str(self._security_group_rule.port_range_min), '--egress', '--ethertype', self._security_group_rule.ethertype, + '--project', identity_fakes.project_name, + '--project-domain', identity_fakes.domain_name, self._security_group.id, ] verifylist = [ @@ -238,6 +265,8 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): self._security_group_rule.port_range_max)), ('egress', True), ('ethertype', self._security_group_rule.ethertype), + ('project', identity_fakes.project_name), + ('project_domain', identity_fakes.domain_name), ('group', self._security_group.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -251,6 +280,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'port_range_min': self._security_group_rule.port_range_min, 'protocol': self._security_group_rule.protocol, 'security_group_id': self._security_group.id, + 'tenant_id': identity_fakes.project_id, }) self.assertEqual(tuple(self.expected_columns), columns) self.assertEqual(self.expected_data, data) @@ -307,6 +337,17 @@ class TestCreateSecurityGroupRuleCompute(TestSecurityGroupRuleCompute): self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, []) + def test_create_network_options(self): + arglist = [ + '--ingress', + '--ethertype', 'IPv4', + '--project', identity_fakes.project_name, + '--project-domain', identity_fakes.domain_name, + self._security_group.id, + ] + self.assertRaises(tests_utils.ParserException, + self.check_parser, self.cmd, arglist, []) + def test_create_default_rule(self): expected_columns, expected_data = self._setup_security_group_rule() dst_port = str(self._security_group_rule.from_port) + ':' + \ diff --git a/releasenotes/notes/bug-1519512-48d98f09e44220a3.yaml b/releasenotes/notes/bug-1519512-48d98f09e44220a3.yaml index 1d275c573..0161b5cf8 100644 --- a/releasenotes/notes/bug-1519512-48d98f09e44220a3.yaml +++ b/releasenotes/notes/bug-1519512-48d98f09e44220a3.yaml @@ -1,6 +1,7 @@ --- features: - - Add ``--ingress``, ``--egress``, and ``--ethertype`` options to the - ``security group rule create`` command for Network v2 only. These - options enable ``egress`` and ``IPv6`` security group rules. + - Add ``--ingress``, ``--egress``, ``--ethertype``, ``--project`` + and ``--project-domain`` options to the ``security group rule create`` + command for Network v2 only. These options enable ``egress`` and + ``IPv6`` security group rules along with setting the project. [Bug `1519512 `_]