Merge "Network: Add tag support for security group"
This commit is contained in:
commit
4bde9af892
@ -19,6 +19,7 @@ Create a new security group
|
||||
openstack security group create
|
||||
[--description <description>]
|
||||
[--project <project> [--project-domain <project-domain>]]
|
||||
[--tag <tag> | --no-tag]
|
||||
<name>
|
||||
|
||||
.. option:: --description <description>
|
||||
@ -38,6 +39,18 @@ Create a new security group
|
||||
|
||||
*Network version 2 only*
|
||||
|
||||
.. option:: --tag <tag>
|
||||
|
||||
Tag to be added to the security group (repeat option to set multiple tags)
|
||||
|
||||
*Network version 2 only*
|
||||
|
||||
.. option:: --no-tag
|
||||
|
||||
No tags associated with the security group
|
||||
|
||||
*Network version 2 only*
|
||||
|
||||
.. describe:: <name>
|
||||
|
||||
New security group name
|
||||
@ -68,6 +81,8 @@ List security groups
|
||||
openstack security group list
|
||||
[--all-projects]
|
||||
[--project <project> [--project-domain <project-domain>]]
|
||||
[--tags <tag>[,<tag>,...]] [--any-tags <tag>[,<tag>,...]]
|
||||
[--not-tags <tag>[,<tag>,...]] [--not-any-tags <tag>[,<tag>,...]]
|
||||
|
||||
.. option:: --all-projects
|
||||
|
||||
@ -89,6 +104,30 @@ List security groups
|
||||
|
||||
*Network version 2 only*
|
||||
|
||||
.. option:: --tags <tag>[,<tag>,...]
|
||||
|
||||
List security groups which have all given tag(s)
|
||||
|
||||
*Network version 2 only*
|
||||
|
||||
.. option:: --any-tags <tag>[,<tag>,...]
|
||||
|
||||
List security groups which have any given tag(s)
|
||||
|
||||
*Network version 2 only*
|
||||
|
||||
.. option:: --not-tags <tag>[,<tag>,...]
|
||||
|
||||
Exclude security groups which have all given tag(s)
|
||||
|
||||
*Network version 2 only*
|
||||
|
||||
.. option:: --not-any-tags <tag>[,<tag>,...]
|
||||
|
||||
Exclude security groups which have any given tag(s)
|
||||
|
||||
*Network version 2 only*
|
||||
|
||||
security group set
|
||||
------------------
|
||||
|
||||
@ -100,6 +139,7 @@ Set security group properties
|
||||
openstack security group set
|
||||
[--name <new-name>]
|
||||
[--description <description>]
|
||||
[--tag <tag>] [--no-tag]
|
||||
<group>
|
||||
|
||||
.. option:: --name <new-name>
|
||||
@ -110,6 +150,15 @@ Set security group properties
|
||||
|
||||
New security group description
|
||||
|
||||
.. option:: --tag <tag>
|
||||
|
||||
Tag to be added to the security group (repeat option to set multiple tags)
|
||||
|
||||
.. option:: --no-tag
|
||||
|
||||
Clear tags associated with the security group. Specify both --tag
|
||||
and --no-tag to overwrite current tags
|
||||
|
||||
.. describe:: <group>
|
||||
|
||||
Security group to modify (name or ID)
|
||||
@ -128,3 +177,28 @@ Display security group details
|
||||
.. describe:: <group>
|
||||
|
||||
Security group to display (name or ID)
|
||||
|
||||
security group unset
|
||||
--------------------
|
||||
|
||||
Unset security group properties
|
||||
|
||||
.. program:: security group unset
|
||||
.. code:: bash
|
||||
|
||||
openstack security group unset
|
||||
[--tag <tag> | --all-tag]
|
||||
<group>
|
||||
|
||||
.. option:: --tag <tag>
|
||||
|
||||
Tag to be removed from the security group
|
||||
(repeat option to remove multiple tags)
|
||||
|
||||
.. option:: --all-tag
|
||||
|
||||
Clear all tags associated with the security group
|
||||
|
||||
.. describe:: <group>
|
||||
|
||||
Security group to modify (name or ID)
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
import argparse
|
||||
|
||||
from osc_lib.command import command
|
||||
from osc_lib import utils
|
||||
import six
|
||||
|
||||
@ -23,6 +24,7 @@ from openstackclient.identity import common as identity_common
|
||||
from openstackclient.network import common
|
||||
from openstackclient.network import sdk_utils
|
||||
from openstackclient.network import utils as network_utils
|
||||
from openstackclient.network.v2 import _tag
|
||||
|
||||
|
||||
def _format_network_security_group_rules(sg_rules):
|
||||
@ -106,6 +108,7 @@ class CreateSecurityGroup(common.NetworkAndComputeShowOne):
|
||||
help=_("Owner's project (name or ID)")
|
||||
)
|
||||
identity_common.add_project_domain_option_to_parser(parser)
|
||||
_tag.add_tag_option_to_parser_for_create(parser, _('security group'))
|
||||
return parser
|
||||
|
||||
def _get_description(self, parsed_args):
|
||||
@ -130,6 +133,8 @@ class CreateSecurityGroup(common.NetworkAndComputeShowOne):
|
||||
|
||||
# Create the security group and display the results.
|
||||
obj = client.create_security_group(**attrs)
|
||||
# tags cannot be set when created, so tags need to be set later.
|
||||
_tag.update_tags_for_set(client, obj, parsed_args)
|
||||
display_columns, property_columns = _get_columns(obj)
|
||||
data = utils.get_item_properties(
|
||||
obj,
|
||||
@ -198,6 +203,7 @@ class ListSecurityGroup(common.NetworkAndComputeLister):
|
||||
"(name or ID)")
|
||||
)
|
||||
identity_common.add_project_domain_option_to_parser(parser)
|
||||
_tag.add_tag_filtering_option_to_parser(parser, _('security group'))
|
||||
return parser
|
||||
|
||||
def update_parser_compute(self, parser):
|
||||
@ -220,19 +226,23 @@ class ListSecurityGroup(common.NetworkAndComputeLister):
|
||||
).id
|
||||
filters['tenant_id'] = project_id
|
||||
filters['project_id'] = project_id
|
||||
|
||||
_tag.get_tag_filtering_args(parsed_args, filters)
|
||||
data = client.security_groups(**filters)
|
||||
|
||||
columns = (
|
||||
"ID",
|
||||
"Name",
|
||||
"Description",
|
||||
"Project ID"
|
||||
"Project ID",
|
||||
"tags"
|
||||
)
|
||||
column_headers = (
|
||||
"ID",
|
||||
"Name",
|
||||
"Description",
|
||||
"Project"
|
||||
"Project",
|
||||
"Tags"
|
||||
)
|
||||
return (column_headers,
|
||||
(utils.get_item_properties(
|
||||
@ -282,6 +292,10 @@ class SetSecurityGroup(common.NetworkAndComputeCommand):
|
||||
)
|
||||
return parser
|
||||
|
||||
def update_parser_network(self, parser):
|
||||
_tag.add_tag_option_to_parser_for_set(parser, _('security group'))
|
||||
return parser
|
||||
|
||||
def take_action_network(self, client, parsed_args):
|
||||
obj = client.find_security_group(parsed_args.group,
|
||||
ignore_missing=False)
|
||||
@ -295,6 +309,9 @@ class SetSecurityGroup(common.NetworkAndComputeCommand):
|
||||
# the update.
|
||||
client.update_security_group(obj, **attrs)
|
||||
|
||||
# tags is a subresource and it needs to be updated separately.
|
||||
_tag.update_tags_for_set(client, obj, parsed_args)
|
||||
|
||||
def take_action_compute(self, client, parsed_args):
|
||||
data = client.api.security_group_find(parsed_args.group)
|
||||
|
||||
@ -344,3 +361,25 @@ class ShowSecurityGroup(common.NetworkAndComputeShowOne):
|
||||
formatters=_formatters_compute
|
||||
)
|
||||
return (display_columns, data)
|
||||
|
||||
|
||||
class UnsetSecurityGroup(command.Command):
|
||||
_description = _("Unset security group properties")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(UnsetSecurityGroup, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'group',
|
||||
metavar="<group>",
|
||||
help=_("Security group to modify (name or ID)")
|
||||
)
|
||||
_tag.add_tag_option_to_parser_for_unset(parser, _('security group'))
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.network
|
||||
obj = client.find_security_group(parsed_args.group,
|
||||
ignore_missing=False)
|
||||
|
||||
# tags is a subresource and it needs to be updated separately.
|
||||
_tag.update_tags_for_unset(client, obj, parsed_args)
|
||||
|
@ -1132,6 +1132,7 @@ class FakeSecurityGroup(object):
|
||||
'description': 'security-group-description-' + uuid.uuid4().hex,
|
||||
'project_id': 'project-id-' + uuid.uuid4().hex,
|
||||
'security_group_rules': [],
|
||||
'tags': []
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
|
@ -40,8 +40,8 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
project = identity_fakes.FakeProject.create_one_project()
|
||||
domain = identity_fakes.FakeDomain.create_one_domain()
|
||||
# The security group to be created.
|
||||
_security_group = \
|
||||
network_fakes.FakeSecurityGroup.create_one_security_group()
|
||||
_security_group = (
|
||||
network_fakes.FakeSecurityGroup.create_one_security_group())
|
||||
|
||||
columns = (
|
||||
'description',
|
||||
@ -49,6 +49,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
'name',
|
||||
'project_id',
|
||||
'rules',
|
||||
'tags',
|
||||
)
|
||||
|
||||
data = (
|
||||
@ -57,6 +58,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
_security_group.name,
|
||||
_security_group.project_id,
|
||||
'',
|
||||
_security_group.tags,
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
@ -67,6 +69,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
|
||||
self.projects_mock.get.return_value = self.project
|
||||
self.domains_mock.get.return_value = self.domain
|
||||
self.network.set_tags = mock.Mock(return_value=None)
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = security_group.CreateSecurityGroup(self.app, self.namespace)
|
||||
@ -118,6 +121,43 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
def _test_create_with_tag(self, add_tags=True):
|
||||
arglist = [self._security_group.name]
|
||||
if add_tags:
|
||||
arglist += ['--tag', 'red', '--tag', 'blue']
|
||||
else:
|
||||
arglist += ['--no-tag']
|
||||
|
||||
verifylist = [
|
||||
('name', self._security_group.name),
|
||||
]
|
||||
if add_tags:
|
||||
verifylist.append(('tags', ['red', 'blue']))
|
||||
else:
|
||||
verifylist.append(('no_tag', True))
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = (self.cmd.take_action(parsed_args))
|
||||
|
||||
self.network.create_security_group.assert_called_once_with(**{
|
||||
'description': self._security_group.name,
|
||||
'name': self._security_group.name,
|
||||
})
|
||||
if add_tags:
|
||||
self.network.set_tags.assert_called_once_with(
|
||||
self._security_group,
|
||||
tests_utils.CompareBySet(['red', 'blue']))
|
||||
else:
|
||||
self.assertFalse(self.network.set_tags.called)
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
def test_create_with_tags(self):
|
||||
self._test_create_with_tag(add_tags=True)
|
||||
|
||||
def test_create_with_no_tag(self):
|
||||
self._test_create_with_tag(add_tags=False)
|
||||
|
||||
|
||||
class TestDeleteSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
|
||||
@ -214,6 +254,7 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
'Name',
|
||||
'Description',
|
||||
'Project',
|
||||
'Tags',
|
||||
)
|
||||
|
||||
data = []
|
||||
@ -223,6 +264,7 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
grp.name,
|
||||
grp.description,
|
||||
grp.project_id,
|
||||
grp.tags,
|
||||
))
|
||||
|
||||
def setUp(self):
|
||||
@ -300,12 +342,38 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, list(data))
|
||||
|
||||
def test_list_with_tag_options(self):
|
||||
arglist = [
|
||||
'--tags', 'red,blue',
|
||||
'--any-tags', 'red,green',
|
||||
'--not-tags', 'orange,yellow',
|
||||
'--not-any-tags', 'black,white',
|
||||
]
|
||||
verifylist = [
|
||||
('tags', ['red', 'blue']),
|
||||
('any_tags', ['red', 'green']),
|
||||
('not_tags', ['orange', 'yellow']),
|
||||
('not_any_tags', ['black', 'white']),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.network.security_groups.assert_called_once_with(
|
||||
**{'tags': 'red,blue',
|
||||
'any_tags': 'red,green',
|
||||
'not_tags': 'orange,yellow',
|
||||
'not_any_tags': 'black,white'}
|
||||
)
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, list(data))
|
||||
|
||||
|
||||
class TestSetSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
|
||||
# The security group to be set.
|
||||
_security_group = \
|
||||
network_fakes.FakeSecurityGroup.create_one_security_group()
|
||||
_security_group = (
|
||||
network_fakes.FakeSecurityGroup.create_one_security_group(
|
||||
attrs={'tags': ['green', 'red']}))
|
||||
|
||||
def setUp(self):
|
||||
super(TestSetSecurityGroupNetwork, self).setUp()
|
||||
@ -314,6 +382,7 @@ class TestSetSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
|
||||
self.network.find_security_group = mock.Mock(
|
||||
return_value=self._security_group)
|
||||
self.network.set_tags = mock.Mock(return_value=None)
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = security_group.SetSecurityGroup(self.app, self.namespace)
|
||||
@ -366,6 +435,34 @@ class TestSetSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def _test_set_tags(self, with_tags=True):
|
||||
if with_tags:
|
||||
arglist = ['--tag', 'red', '--tag', 'blue']
|
||||
verifylist = [('tags', ['red', 'blue'])]
|
||||
expected_args = ['red', 'blue', 'green']
|
||||
else:
|
||||
arglist = ['--no-tag']
|
||||
verifylist = [('no_tag', True)]
|
||||
expected_args = []
|
||||
arglist.append(self._security_group.name)
|
||||
verifylist.append(
|
||||
('group', self._security_group.name))
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.assertTrue(self.network.update_security_group.called)
|
||||
self.network.set_tags.assert_called_once_with(
|
||||
self._security_group,
|
||||
tests_utils.CompareBySet(expected_args))
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_set_with_tags(self):
|
||||
self._test_set_tags(with_tags=True)
|
||||
|
||||
def test_set_with_no_tag(self):
|
||||
self._test_set_tags(with_tags=False)
|
||||
|
||||
|
||||
class TestShowSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
|
||||
@ -385,6 +482,7 @@ class TestShowSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
'name',
|
||||
'project_id',
|
||||
'rules',
|
||||
'tags',
|
||||
)
|
||||
|
||||
data = (
|
||||
@ -394,6 +492,7 @@ class TestShowSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
_security_group.project_id,
|
||||
security_group._format_network_security_group_rules(
|
||||
[_security_group_rule._info]),
|
||||
_security_group.tags,
|
||||
)
|
||||
|
||||
def setUp(self):
|
||||
@ -424,3 +523,70 @@ class TestShowSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
self._security_group.id, ignore_missing=False)
|
||||
self.assertEqual(self.columns, columns)
|
||||
self.assertEqual(self.data, data)
|
||||
|
||||
|
||||
class TestUnsetSecurityGroupNetwork(TestSecurityGroupNetwork):
|
||||
|
||||
# The security group to be unset.
|
||||
_security_group = (
|
||||
network_fakes.FakeSecurityGroup.create_one_security_group(
|
||||
attrs={'tags': ['green', 'red']}))
|
||||
|
||||
def setUp(self):
|
||||
super(TestUnsetSecurityGroupNetwork, self).setUp()
|
||||
|
||||
self.network.update_security_group = mock.Mock(return_value=None)
|
||||
|
||||
self.network.find_security_group = mock.Mock(
|
||||
return_value=self._security_group)
|
||||
self.network.set_tags = mock.Mock(return_value=None)
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = security_group.UnsetSecurityGroup(self.app, self.namespace)
|
||||
|
||||
def test_set_no_options(self):
|
||||
self.assertRaises(tests_utils.ParserException,
|
||||
self.check_parser, self.cmd, [], [])
|
||||
|
||||
def test_set_no_updates(self):
|
||||
arglist = [
|
||||
self._security_group.name,
|
||||
]
|
||||
verifylist = [
|
||||
('group', self._security_group.name),
|
||||
]
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.assertFalse(self.network.update_security_group.called)
|
||||
self.assertFalse(self.network.set_tags.called)
|
||||
self.assertIsNone(result)
|
||||
|
||||
def _test_unset_tags(self, with_tags=True):
|
||||
if with_tags:
|
||||
arglist = ['--tag', 'red', '--tag', 'blue']
|
||||
verifylist = [('tags', ['red', 'blue'])]
|
||||
expected_args = ['green']
|
||||
else:
|
||||
arglist = ['--all-tag']
|
||||
verifylist = [('all_tag', True)]
|
||||
expected_args = []
|
||||
arglist.append(self._security_group.name)
|
||||
verifylist.append(
|
||||
('group', self._security_group.name))
|
||||
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
self.assertFalse(self.network.update_security_group.called)
|
||||
self.network.set_tags.assert_called_once_with(
|
||||
self._security_group,
|
||||
tests_utils.CompareBySet(expected_args))
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_unset_with_tags(self):
|
||||
self._test_unset_tags(with_tags=True)
|
||||
|
||||
def test_unset_with_all_tag(self):
|
||||
self._test_unset_tags(with_tags=False)
|
||||
|
8
releasenotes/notes/bug-1750983-420945d6c0afb509.yaml
Normal file
8
releasenotes/notes/bug-1750983-420945d6c0afb509.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
---
|
||||
fixes:
|
||||
- |
|
||||
Add supports tagging for Network security group.
|
||||
Add ``tag``, ``no-tag`` to ``security group create`` and ``security group set`` commands.
|
||||
Add ``tags``, ``any-tags``, ``not-tags``, ``not-any-tags`` to ``security group list`` command.
|
||||
Add ``tag`` and ``all-tag`` to ``security group unset`` command.
|
||||
[Bug `1750983 <https://bugs.launchpad.net/python-openstackclient/+bug/1750983>`_]
|
@ -474,6 +474,7 @@ openstack.network.v2 =
|
||||
security_group_list = openstackclient.network.v2.security_group:ListSecurityGroup
|
||||
security_group_set = openstackclient.network.v2.security_group:SetSecurityGroup
|
||||
security_group_show = openstackclient.network.v2.security_group:ShowSecurityGroup
|
||||
security_group_unset = openstackclient.network.v2.security_group:UnsetSecurityGroup
|
||||
|
||||
security_group_rule_create = openstackclient.network.v2.security_group_rule:CreateSecurityGroupRule
|
||||
security_group_rule_delete = openstackclient.network.v2.security_group_rule:DeleteSecurityGroupRule
|
||||
|
Loading…
x
Reference in New Issue
Block a user