summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Castro Leon <jose.castro.leon@cern.ch>2019-03-14 12:33:51 +0000
committerMarc GariƩpy (mgariepy) <gariepy.marc@gmail.com>2019-06-27 18:36:30 +0000
commitbb7f49168563414d65b4050e84a8d1d4915206bc (patch)
tree5c6cd755ddcf43e3f32b5f8c689c549247f52fe5
parent45889660f332c38ef597771f7fed0810f4919880 (diff)
downloadpython-openstackclient-bb7f49168563414d65b4050e84a8d1d4915206bc.tar.gz
Fix bug in endpoint group deletion
There is a typo in the endpoint group deletion, due to this you can't remove endpoint groups once assigned. I am adding also the unit tests to avoid this kind of issues in the future Task: 30640 Story: 2005521 Change-Id: Ie938f2c9894bb39b4c0ed1f7aa3a6a751a303058 (cherry picked from commit 04e03b2a1fe34046e2148d3c1d17b9053010c8af)
-rw-r--r--openstackclient/identity/v3/endpoint_group.py6
-rw-r--r--openstackclient/tests/unit/identity/v3/fakes.py62
-rw-r--r--openstackclient/tests/unit/identity/v3/test_endpoint_group.py495
-rw-r--r--releasenotes/notes/bug-2005521-0274fc26bd9b3842.yaml5
4 files changed, 565 insertions, 3 deletions
diff --git a/openstackclient/identity/v3/endpoint_group.py b/openstackclient/identity/v3/endpoint_group.py
index e254973b..66bd164d 100644
--- a/openstackclient/identity/v3/endpoint_group.py
+++ b/openstackclient/identity/v3/endpoint_group.py
@@ -204,11 +204,11 @@ class ListEndpointGroup(command.Lister):
if endpointgroup:
# List projects associated to the endpoint group
- columns = ('ID', 'Name')
+ columns = ('ID', 'Name', 'Description')
data = client.endpoint_filter.list_projects_for_endpoint_group(
endpoint_group=endpointgroup.id)
elif project:
- columns = ('ID', 'Name')
+ columns = ('ID', 'Name', 'Description')
data = client.endpoint_filter.list_endpoint_groups_for_project(
project=project.id)
else:
@@ -251,7 +251,7 @@ class RemoveProjectFromEndpointGroup(command.Command):
parsed_args.project,
parsed_args.project_domain)
- client.endpoint_filter.delete_endpoint_group_to_project(
+ client.endpoint_filter.delete_endpoint_group_from_project(
endpoint_group=endpointgroup.id,
project=project.id)
diff --git a/openstackclient/tests/unit/identity/v3/fakes.py b/openstackclient/tests/unit/identity/v3/fakes.py
index 27ee9fd0..e5727a6a 100644
--- a/openstackclient/tests/unit/identity/v3/fakes.py
+++ b/openstackclient/tests/unit/identity/v3/fakes.py
@@ -235,6 +235,10 @@ endpoint_group_filters = {
'service_id': service_id,
'region_id': endpoint_region,
}
+endpoint_group_filters_2 = {
+ 'region_id': endpoint_region,
+}
+endpoint_group_file_path = '/tmp/path/to/file'
ENDPOINT_GROUP = {
'id': endpoint_group_id,
@@ -1044,6 +1048,64 @@ class FakeEndpoint(object):
return endpoint_filter
+class FakeEndpointGroup(object):
+ """Fake one or more endpoint group."""
+
+ @staticmethod
+ def create_one_endpointgroup(attrs=None):
+ """Create a fake endpoint group.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object, with id, url, and so on
+ """
+
+ attrs = attrs or {}
+
+ # set default attributes.
+ endpointgroup_info = {
+ 'id': 'endpoint-group-id-' + uuid.uuid4().hex,
+ 'name': 'endpoint-group-name-' + uuid.uuid4().hex,
+ 'filters': {
+ 'region': 'region-' + uuid.uuid4().hex,
+ 'service_id': 'service-id-' + uuid.uuid4().hex,
+ },
+ 'description': 'endpoint-group-description-' + uuid.uuid4().hex,
+ 'links': 'links-' + uuid.uuid4().hex,
+ }
+ endpointgroup_info.update(attrs)
+
+ endpoint = fakes.FakeResource(info=copy.deepcopy(endpointgroup_info),
+ loaded=True)
+ return endpoint
+
+ @staticmethod
+ def create_one_endpointgroup_filter(attrs=None):
+ """Create a fake endpoint project relationship.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes of endpointgroup filter
+ :return:
+ A FakeResource object with project, endpointgroup and so on
+ """
+ attrs = attrs or {}
+
+ # Set default attribute
+ endpointgroup_filter_info = {
+ 'project': 'project-id-' + uuid.uuid4().hex,
+ 'endpointgroup': 'endpointgroup-id-' + uuid.uuid4().hex,
+ }
+
+ # Overwrite default attributes if there are some attributes set
+ endpointgroup_filter_info.update(attrs)
+
+ endpointgroup_filter = fakes.FakeModel(
+ copy.deepcopy(endpointgroup_filter_info))
+
+ return endpointgroup_filter
+
+
class FakeService(object):
"""Fake one or more service."""
diff --git a/openstackclient/tests/unit/identity/v3/test_endpoint_group.py b/openstackclient/tests/unit/identity/v3/test_endpoint_group.py
new file mode 100644
index 00000000..6e9da9c7
--- /dev/null
+++ b/openstackclient/tests/unit/identity/v3/test_endpoint_group.py
@@ -0,0 +1,495 @@
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+
+import mock
+
+from openstackclient.identity.v3 import endpoint_group
+from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
+
+
+class TestEndpointGroup(identity_fakes.TestIdentityv3):
+
+ def setUp(self):
+ super(TestEndpointGroup, self).setUp()
+
+ # Get a shortcut to the EndpointManager Mock
+ self.endpoint_groups_mock = (
+ self.app.client_manager.identity.endpoint_groups
+ )
+ self.endpoint_groups_mock.reset_mock()
+ self.epf_mock = (
+ self.app.client_manager.identity.endpoint_filter
+ )
+ self.epf_mock.reset_mock()
+
+ # Get a shortcut to the ServiceManager Mock
+ self.services_mock = self.app.client_manager.identity.services
+ self.services_mock.reset_mock()
+
+ # Get a shortcut to the DomainManager Mock
+ self.domains_mock = self.app.client_manager.identity.domains
+ self.domains_mock.reset_mock()
+
+ # Get a shortcut to the ProjectManager Mock
+ self.projects_mock = self.app.client_manager.identity.projects
+ self.projects_mock.reset_mock()
+
+
+class TestEndpointGroupCreate(TestEndpointGroup):
+
+ columns = (
+ 'description',
+ 'filters',
+ 'id',
+ 'name',
+ )
+
+ def setUp(self):
+ super(TestEndpointGroupCreate, self).setUp()
+
+ self.endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup(
+ attrs={'filters': identity_fakes.endpoint_group_filters}))
+
+ self.endpoint_groups_mock.create.return_value = self.endpoint_group
+
+ # Get the command object to test
+ self.cmd = endpoint_group.CreateEndpointGroup(self.app, None)
+
+ def test_endpointgroup_create_no_options(self):
+ arglist = [
+ '--description', self.endpoint_group.description,
+ self.endpoint_group.name,
+ identity_fakes.endpoint_group_file_path,
+ ]
+ verifylist = [
+ ('name', self.endpoint_group.name),
+ ('filters', identity_fakes.endpoint_group_file_path),
+ ('description', self.endpoint_group.description),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ mocker = mock.Mock()
+ mocker.return_value = identity_fakes.endpoint_group_filters
+ with mock.patch("openstackclient.identity.v3.endpoint_group."
+ "CreateEndpointGroup._read_filters", mocker):
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'name': self.endpoint_group.name,
+ 'filters': identity_fakes.endpoint_group_filters,
+ 'description': self.endpoint_group.description,
+ }
+
+ self.endpoint_groups_mock.create.assert_called_with(
+ **kwargs
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ self.endpoint_group.description,
+ identity_fakes.endpoint_group_filters,
+ self.endpoint_group.id,
+ self.endpoint_group.name,
+ )
+ self.assertEqual(datalist, data)
+
+
+class TestEndpointGroupDelete(TestEndpointGroup):
+
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+
+ def setUp(self):
+ super(TestEndpointGroupDelete, self).setUp()
+
+ # This is the return value for utils.find_resource(endpoint)
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+ self.endpoint_groups_mock.delete.return_value = None
+
+ # Get the command object to test
+ self.cmd = endpoint_group.DeleteEndpointGroup(self.app, None)
+
+ def test_endpointgroup_delete(self):
+ arglist = [
+ self.endpoint_group.id,
+ ]
+ verifylist = [
+ ('endpointgroup', [self.endpoint_group.id]),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.endpoint_groups_mock.delete.assert_called_with(
+ self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
+
+
+class TestEndpointGroupList(TestEndpointGroup):
+
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+ project = identity_fakes.FakeProject.create_one_project()
+ domain = identity_fakes.FakeDomain.create_one_domain()
+
+ columns = (
+ 'ID',
+ 'Name',
+ 'Description',
+ )
+
+ def setUp(self):
+ super(TestEndpointGroupList, self).setUp()
+
+ self.endpoint_groups_mock.list.return_value = [self.endpoint_group]
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+ self.epf_mock.list_projects_for_endpoint_group.return_value = [
+ self.project]
+ self.epf_mock.list_endpoint_groups_for_project.return_value = [
+ self.endpoint_group]
+
+ # Get the command object to test
+ self.cmd = endpoint_group.ListEndpointGroup(self.app, None)
+
+ def test_endpoint_group_list_no_options(self):
+ arglist = []
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+ self.endpoint_groups_mock.list.assert_called_with()
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ (
+ self.endpoint_group.id,
+ self.endpoint_group.name,
+ self.endpoint_group.description,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
+
+ def test_endpoint_group_list_projects_by_endpoint_group(self):
+ arglist = [
+ '--endpointgroup', self.endpoint_group.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+ self.epf_mock.list_projects_for_endpoint_group.assert_called_with(
+ endpoint_group=self.endpoint_group.id
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ (
+ self.project.id,
+ self.project.name,
+ self.project.description,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
+
+ def test_endpoint_group_list_by_project(self):
+ self.epf_mock.list_endpoints_for_project.return_value = [
+ self.endpoint_group
+ ]
+ self.projects_mock.get.return_value = self.project
+
+ arglist = [
+ '--project', self.project.name,
+ '--domain', self.domain.name
+ ]
+ verifylist = [
+ ('project', self.project.name),
+ ('domain', self.domain.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+ self.epf_mock.list_endpoint_groups_for_project.assert_called_with(
+ project=self.project.id
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ (
+ self.endpoint_group.id,
+ self.endpoint_group.name,
+ self.endpoint_group.description,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
+
+
+class TestEndpointGroupSet(TestEndpointGroup):
+
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+
+ def setUp(self):
+ super(TestEndpointGroupSet, self).setUp()
+
+ # This is the return value for utils.find_resource(endpoint)
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+
+ self.endpoint_groups_mock.update.return_value = self.endpoint_group
+
+ # Get the command object to test
+ self.cmd = endpoint_group.SetEndpointGroup(self.app, None)
+
+ def test_endpoint_group_set_no_options(self):
+ arglist = [
+ self.endpoint_group.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ kwargs = {
+ 'name': None,
+ 'filters': None,
+ 'description': ''
+ }
+ self.endpoint_groups_mock.update.assert_called_with(
+ self.endpoint_group.id,
+ **kwargs
+ )
+ self.assertIsNone(result)
+
+ def test_endpoint_group_set_name(self):
+ arglist = [
+ '--name', 'qwerty',
+ self.endpoint_group.id
+ ]
+ verifylist = [
+ ('name', 'qwerty'),
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'name': 'qwerty',
+ 'filters': None,
+ 'description': ''
+ }
+ self.endpoint_groups_mock.update.assert_called_with(
+ self.endpoint_group.id,
+ **kwargs
+ )
+ self.assertIsNone(result)
+
+ def test_endpoint_group_set_filters(self):
+ arglist = [
+ '--filters', identity_fakes.endpoint_group_file_path,
+ self.endpoint_group.id,
+ ]
+ verifylist = [
+ ('filters', identity_fakes.endpoint_group_file_path),
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ mocker = mock.Mock()
+ mocker.return_value = identity_fakes.endpoint_group_filters_2
+ with mock.patch("openstackclient.identity.v3.endpoint_group."
+ "SetEndpointGroup._read_filters", mocker):
+ result = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'name': None,
+ 'filters': identity_fakes.endpoint_group_filters_2,
+ 'description': '',
+ }
+
+ self.endpoint_groups_mock.update.assert_called_with(
+ self.endpoint_group.id,
+ **kwargs
+ )
+
+ self.assertIsNone(result)
+
+ def test_endpoint_group_set_description(self):
+ arglist = [
+ '--description', 'qwerty',
+ self.endpoint_group.id
+ ]
+ verifylist = [
+ ('description', 'qwerty'),
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'name': None,
+ 'filters': None,
+ 'description': 'qwerty',
+ }
+ self.endpoint_groups_mock.update.assert_called_with(
+ self.endpoint_group.id,
+ **kwargs
+ )
+ self.assertIsNone(result)
+
+
+class TestAddProjectToEndpointGroup(TestEndpointGroup):
+
+ project = identity_fakes.FakeProject.create_one_project()
+ domain = identity_fakes.FakeDomain.create_one_domain()
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+
+ new_ep_filter = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup_filter(
+ attrs={'endpointgroup': endpoint_group.id,
+ 'project': project.id}))
+
+ def setUp(self):
+ super(TestAddProjectToEndpointGroup, self).setUp()
+
+ # This is the return value for utils.find_resource()
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+
+ # Update the image_id in the MEMBER dict
+ self.epf_mock.create.return_value = self.new_ep_filter
+ self.projects_mock.get.return_value = self.project
+ self.domains_mock.get.return_value = self.domain
+
+ # Get the command object to test
+ self.cmd = endpoint_group.AddProjectToEndpointGroup(self.app, None)
+
+ def test_add_project_to_endpoint_no_option(self):
+ arglist = [
+ self.endpoint_group.id,
+ self.project.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ('project', self.project.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.epf_mock.add_endpoint_group_to_project.assert_called_with(
+ project=self.project.id,
+ endpoint_group=self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
+
+ def test_add_project_to_endpoint_with_option(self):
+ arglist = [
+ self.endpoint_group.id,
+ self.project.id,
+ '--project-domain', self.domain.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ('project', self.project.id),
+ ('project_domain', self.domain.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.epf_mock.add_endpoint_group_to_project.assert_called_with(
+ project=self.project.id,
+ endpoint_group=self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
+
+
+class TestRemoveProjectEndpointGroup(TestEndpointGroup):
+
+ project = identity_fakes.FakeProject.create_one_project()
+ domain = identity_fakes.FakeDomain.create_one_domain()
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+
+ def setUp(self):
+ super(TestRemoveProjectEndpointGroup, self).setUp()
+
+ # This is the return value for utils.find_resource()
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+
+ self.projects_mock.get.return_value = self.project
+ self.domains_mock.get.return_value = self.domain
+ self.epf_mock.delete.return_value = None
+
+ # Get the command object to test
+ self.cmd = endpoint_group.RemoveProjectFromEndpointGroup(
+ self.app, None)
+
+ def test_remove_project_endpoint_no_options(self):
+ arglist = [
+ self.endpoint_group.id,
+ self.project.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ('project', self.project.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.epf_mock.delete_endpoint_group_from_project.assert_called_with(
+ project=self.project.id,
+ endpoint_group=self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
+
+ def test_remove_project_endpoint_with_options(self):
+ arglist = [
+ self.endpoint_group.id,
+ self.project.id,
+ '--project-domain', self.domain.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ('project', self.project.id),
+ ('project_domain', self.domain.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.epf_mock.delete_endpoint_group_from_project.assert_called_with(
+ project=self.project.id,
+ endpoint_group=self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
diff --git a/releasenotes/notes/bug-2005521-0274fc26bd9b3842.yaml b/releasenotes/notes/bug-2005521-0274fc26bd9b3842.yaml
new file mode 100644
index 00000000..2d5cacfb
--- /dev/null
+++ b/releasenotes/notes/bug-2005521-0274fc26bd9b3842.yaml
@@ -0,0 +1,5 @@
+---
+fixes:
+ - |
+ Fix ``endpoint group delete`` command to properly delete endpoint groups.
+ [Story `2005521 <https://storyboard.openstack.org/#!/story/2005521>`_] \ No newline at end of file