diff --git a/openstackclient/network/v2/security_group.py b/openstackclient/network/v2/security_group.py index 2033af1432..aec9c56efe 100644 --- a/openstackclient/network/v2/security_group.py +++ b/openstackclient/network/v2/security_group.py @@ -120,6 +120,19 @@ class CreateSecurityGroup(common.NetworkAndComputeShowOne): metavar='', help=self.enhance_help_neutron(_("Owner's project (name or ID)")) ) + stateful_group = parser.add_mutually_exclusive_group() + stateful_group.add_argument( + "--stateful", + action='store_true', + default=None, + help=_("Security group is stateful (Default)") + ) + stateful_group.add_argument( + "--stateless", + action='store_true', + default=None, + help=_("Security group is stateless") + ) identity_common.add_project_domain_option_to_parser( parser, enhance_help=self.enhance_help_neutron) _tag.add_tag_option_to_parser_for_create( @@ -138,6 +151,10 @@ class CreateSecurityGroup(common.NetworkAndComputeShowOne): attrs = {} attrs['name'] = parsed_args.name attrs['description'] = self._get_description(parsed_args) + if parsed_args.stateful: + attrs['stateful'] = True + if parsed_args.stateless: + attrs['stateful'] = False if parsed_args.project is not None: identity_client = self.app.client_manager.identity project_id = identity_common.find_project( @@ -315,6 +332,19 @@ class SetSecurityGroup(common.NetworkAndComputeCommand): metavar="", help=_("New security group description") ) + stateful_group = parser.add_mutually_exclusive_group() + stateful_group.add_argument( + "--stateful", + action='store_true', + default=None, + help=_("Security group is stateful (Default)") + ) + stateful_group.add_argument( + "--stateless", + action='store_true', + default=None, + help=_("Security group is stateless") + ) return parser def update_parser_network(self, parser): @@ -331,6 +361,10 @@ class SetSecurityGroup(common.NetworkAndComputeCommand): attrs['name'] = parsed_args.name if parsed_args.description is not None: attrs['description'] = parsed_args.description + if parsed_args.stateful: + attrs['stateful'] = True + if parsed_args.stateless: + attrs['stateful'] = False # NOTE(rtheis): Previous behavior did not raise a CommandError # if there were no updates. Maintain this behavior and issue # the update. diff --git a/openstackclient/tests/functional/network/v2/test_security_group.py b/openstackclient/tests/functional/network/v2/test_security_group.py index 8ae24b7247..d46f8db787 100644 --- a/openstackclient/tests/functional/network/v2/test_security_group.py +++ b/openstackclient/tests/functional/network/v2/test_security_group.py @@ -42,7 +42,7 @@ class SecurityGroupTests(common.NetworkTests): def test_security_group_set(self): other_name = uuid.uuid4().hex raw_output = self.openstack( - 'security group set --description NSA --name ' + + 'security group set --description NSA --stateless --name ' + other_name + ' ' + self.NAME ) self.assertEqual('', raw_output) @@ -50,8 +50,10 @@ class SecurityGroupTests(common.NetworkTests): cmd_output = json.loads(self.openstack( 'security group show -f json ' + other_name)) self.assertEqual('NSA', cmd_output['description']) + self.assertFalse(cmd_output['stateful']) def test_security_group_show(self): cmd_output = json.loads(self.openstack( 'security group show -f json ' + self.NAME)) self.assertEqual(self.NAME, cmd_output['name']) + self.assertTrue(cmd_output['stateful']) diff --git a/openstackclient/tests/unit/network/v2/fakes.py b/openstackclient/tests/unit/network/v2/fakes.py index cc598834dd..2b88986a27 100644 --- a/openstackclient/tests/unit/network/v2/fakes.py +++ b/openstackclient/tests/unit/network/v2/fakes.py @@ -1227,6 +1227,7 @@ class FakeSecurityGroup(object): 'id': 'security-group-id-' + uuid.uuid4().hex, 'name': 'security-group-name-' + uuid.uuid4().hex, 'description': 'security-group-description-' + uuid.uuid4().hex, + 'stateful': True, 'project_id': 'project-id-' + uuid.uuid4().hex, 'security_group_rules': [], 'tags': [] diff --git a/openstackclient/tests/unit/network/v2/test_security_group_network.py b/openstackclient/tests/unit/network/v2/test_security_group_network.py index 67908fa8bf..7c1d7fb6b0 100644 --- a/openstackclient/tests/unit/network/v2/test_security_group_network.py +++ b/openstackclient/tests/unit/network/v2/test_security_group_network.py @@ -49,6 +49,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork): 'name', 'project_id', 'rules', + 'stateful', 'tags', ) @@ -58,6 +59,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork): _security_group.name, _security_group.project_id, security_group.NetworkSecurityGroupRulesColumn([]), + _security_group.stateful, _security_group.tags, ) @@ -101,6 +103,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork): '--description', self._security_group.description, '--project', self.project.name, '--project-domain', self.domain.name, + '--stateful', self._security_group.name, ] verifylist = [ @@ -108,6 +111,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork): ('name', self._security_group.name), ('project', self.project.name), ('project_domain', self.domain.name), + ('stateful', self._security_group.stateful), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -115,6 +119,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork): self.network.create_security_group.assert_called_once_with(**{ 'description': self._security_group.description, + 'stateful': self._security_group.stateful, 'name': self._security_group.name, 'tenant_id': self.project.id, }) @@ -421,11 +426,13 @@ class TestSetSecurityGroupNetwork(TestSecurityGroupNetwork): arglist = [ '--name', new_name, '--description', new_description, + '--stateful', self._security_group.name, ] verifylist = [ ('description', new_description), ('group', self._security_group.name), + ('stateful', self._security_group.stateful), ('name', new_name), ] @@ -435,6 +442,7 @@ class TestSetSecurityGroupNetwork(TestSecurityGroupNetwork): attrs = { 'description': new_description, 'name': new_name, + 'stateful': True, } self.network.update_security_group.assert_called_once_with( self._security_group, @@ -489,6 +497,7 @@ class TestShowSecurityGroupNetwork(TestSecurityGroupNetwork): 'name', 'project_id', 'rules', + 'stateful', 'tags', ) @@ -499,6 +508,7 @@ class TestShowSecurityGroupNetwork(TestSecurityGroupNetwork): _security_group.project_id, security_group.NetworkSecurityGroupRulesColumn( [_security_group_rule._info]), + _security_group.stateful, _security_group.tags, ) diff --git a/releasenotes/notes/stateful-security-group-a21fa8498e866b90.yaml b/releasenotes/notes/stateful-security-group-a21fa8498e866b90.yaml new file mode 100644 index 0000000000..9b70bce86c --- /dev/null +++ b/releasenotes/notes/stateful-security-group-a21fa8498e866b90.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Add ``--stateful`` and ``--stateless`` option to the + ``security group create`` and ``security group set`` commands + to support stateful and stateless security groups.