summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorJordan Pittier <jordan.pittier@scality.com>2016-12-15 22:20:30 +0100
committerJordan Pittier <jordan.pittier@scality.com>2017-01-04 19:26:01 +0100
commitf055fe67c11fff020ae959b1672844aaff382491 (patch)
tree5f05551742886962d24d4e38efb7a5b810b29810 /openstackclient
parentc416aecb2f7fc8e993ca2b22edd4dea3673d2cac (diff)
downloadpython-openstackclient-f055fe67c11fff020ae959b1672844aaff382491.tar.gz
Add support for Glance 'update image members' feature
This patch adds 3 new options to the "image set" command: --accept, --reject and --pending. This updates the membership status for an image. Closes-Bug: 1620481 Change-Id: I13b8c067aad68ece9ff636fbdd83bcb3663c91b2
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/image/v2/image.py36
-rw-r--r--openstackclient/tests/functional/image/v2/test_image.py22
-rw-r--r--openstackclient/tests/unit/image/v2/test_image.py33
3 files changed, 90 insertions, 1 deletions
diff --git a/openstackclient/image/v2/image.py b/openstackclient/image/v2/image.py
index 55eb7eb1..418cc397 100644
--- a/openstackclient/image/v2/image.py
+++ b/openstackclient/image/v2/image.py
@@ -777,6 +777,23 @@ class SetImage(command.Command):
dest=deadopt.replace('-', '_'),
help=argparse.SUPPRESS,
)
+
+ membership_group = parser.add_mutually_exclusive_group()
+ membership_group.add_argument(
+ "--accept",
+ action="store_true",
+ help=_("Accept the image membership"),
+ )
+ membership_group.add_argument(
+ "--reject",
+ action="store_true",
+ help=_("Reject the image membership"),
+ )
+ membership_group.add_argument(
+ "--pending",
+ action="store_true",
+ help=_("Reset the image membership to 'pending'"),
+ )
return parser
def take_action(self, parsed_args):
@@ -828,12 +845,14 @@ class SetImage(command.Command):
project_arg = parsed_args.owner
LOG.warning(_('The --owner option is deprecated, '
'please use --project instead.'))
+ project_id = None
if project_arg:
- kwargs['owner'] = common.find_project(
+ project_id = common.find_project(
identity_client,
project_arg,
parsed_args.project_domain,
).id
+ kwargs['owner'] = project_id
image = utils.find_resource(
image_client.images, parsed_args.image)
@@ -846,6 +865,21 @@ class SetImage(command.Command):
image_client.images.reactivate(image.id)
activation_status = "activated"
+ membership_group_args = ('accept', 'reject', 'pending')
+ membership_status = [status for status in membership_group_args
+ if getattr(parsed_args, status)]
+ if membership_status:
+ # If a specific project is not passed, assume we want to update
+ # our own membership
+ if not project_id:
+ project_id = self.app.client_manager.auth_ref.project_id
+ # The mutually exclusive group of the arg parser ensure we have at
+ # most one item in the membership_status list.
+ if membership_status[0] != 'pending':
+ membership_status[0] += 'ed' # Glance expects the past form
+ image_client.image_members.update(
+ image.id, project_id, membership_status[0])
+
if parsed_args.tags:
# Tags should be extended, but duplicates removed
kwargs['tags'] = list(set(image.tags).union(set(parsed_args.tags)))
diff --git a/openstackclient/tests/functional/image/v2/test_image.py b/openstackclient/tests/functional/image/v2/test_image.py
index 3f432b02..6faff94a 100644
--- a/openstackclient/tests/functional/image/v2/test_image.py
+++ b/openstackclient/tests/functional/image/v2/test_image.py
@@ -74,3 +74,25 @@ class ImageTests(base.TestCase):
self.openstack('image unset --property a --property c ' + self.NAME)
raw_output = self.openstack('image show ' + self.NAME + opts)
self.assertEqual(self.NAME + "\n\n", raw_output)
+
+ def test_image_members(self):
+ opts = self.get_opts(['project_id'])
+ my_project_id = self.openstack('token issue' + opts).strip()
+ self.openstack(
+ 'image add project {} {}'.format(self.NAME, my_project_id))
+
+ self.openstack(
+ 'image set --accept ' + self.NAME)
+ shared_img_list = self.parse_listing(
+ self.openstack('image list --shared', self.get_opts(['name']))
+ )
+ self.assertIn(self.NAME, [img['Name'] for img in shared_img_list])
+
+ self.openstack(
+ 'image set --reject ' + self.NAME)
+ shared_img_list = self.parse_listing(
+ self.openstack('image list --shared', self.get_opts(['name']))
+ )
+
+ self.openstack(
+ 'image remove project {} {}'.format(self.NAME, my_project_id))
diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py
index a054e513..a1513119 100644
--- a/openstackclient/tests/unit/image/v2/test_image.py
+++ b/openstackclient/tests/unit/image/v2/test_image.py
@@ -845,6 +845,39 @@ class TestImageSet(TestImage):
self.assertIsNone(result)
+ self.image_members_mock.update.assert_not_called()
+
+ def test_image_set_membership_option(self):
+ membership = image_fakes.FakeImage.create_one_image_member(
+ attrs={'image_id': image_fakes.image_id,
+ 'member_id': self.project.id}
+ )
+ self.image_members_mock.update.return_value = membership
+
+ for status in ('accept', 'reject', 'pending'):
+ arglist = [
+ '--%s' % status,
+ image_fakes.image_id,
+ ]
+ verifylist = [
+ (status, True),
+ ('image', image_fakes.image_id)
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ self.cmd.take_action(parsed_args)
+
+ self.image_members_mock.update.assert_called_once_with(
+ image_fakes.image_id,
+ self.app.client_manager.auth_ref.project_id,
+ status if status == 'pending' else status + 'ed'
+ )
+ self.image_members_mock.update.reset_mock()
+
+ # Assert that the 'update image" route is also called, in addition to
+ # the 'update membership' route.
+ self.images_mock.update.assert_called_with(image_fakes.image_id)
+
def test_image_set_options(self):
arglist = [
'--name', 'new-name',