Begin low-level API for Image v1 and v2
image list for v1 and v2: * Add --public|--private to command parsers * Implement local public/private filtering for v1 image_list() * Pass public/private filter to server for v2 image_list() Change-Id: Ie7c24ea2d1bf2b3b1b7fa342eb45fee45894634d
This commit is contained in:
parent
95fe3fda3d
commit
1ecf1bee2d
@ -139,12 +139,21 @@ List available images
|
||||
|
||||
os image list
|
||||
[--page-size <size>]
|
||||
[--public|--private]
|
||||
[--long]
|
||||
|
||||
.. option:: --page-size <size>
|
||||
|
||||
Number of images to request in each paginated request
|
||||
|
||||
.. option:: --public
|
||||
|
||||
List only public images
|
||||
|
||||
.. option:: --private
|
||||
|
||||
List only private images
|
||||
|
||||
.. option:: --long
|
||||
|
||||
List additional fields in output
|
||||
|
@ -161,7 +161,7 @@ class BaseAPI(KeystoneSession):
|
||||
):
|
||||
"""Return a list of resources
|
||||
|
||||
GET ${ENDPOINT}/${PATH}
|
||||
GET ${ENDPOINT}/${PATH}?${PARAMS}
|
||||
|
||||
path is often the object's plural resource type
|
||||
|
||||
|
68
openstackclient/api/image_v1.py
Normal file
68
openstackclient/api/image_v1.py
Normal file
@ -0,0 +1,68 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Image v1 API Library"""
|
||||
|
||||
from openstackclient.api import api
|
||||
|
||||
|
||||
class APIv1(api.BaseAPI):
|
||||
"""Image v1 API"""
|
||||
|
||||
def __init__(self, endpoint=None, **kwargs):
|
||||
super(APIv1, self).__init__(endpoint=endpoint, **kwargs)
|
||||
|
||||
# Hack this until discovery is up
|
||||
self.endpoint = '/'.join([self.endpoint.rstrip('/'), 'v1'])
|
||||
|
||||
def image_list(
|
||||
self,
|
||||
detailed=False,
|
||||
public=False,
|
||||
private=False,
|
||||
**filter
|
||||
):
|
||||
"""Get available images
|
||||
|
||||
:param detailed:
|
||||
Retrieve detailed response from server if True
|
||||
:param public:
|
||||
Return public images if True
|
||||
:param private:
|
||||
Return private images if True
|
||||
|
||||
If public and private are both True or both False then all images are
|
||||
returned. Both arguments False is equivalent to no filter and all
|
||||
images are returned. Both arguments True is a filter that includes
|
||||
both public and private images which is the same set as all images.
|
||||
|
||||
http://docs.openstack.org/api/openstack-image-service/1.1/content/requesting-a-list-of-public-vm-images.html
|
||||
http://docs.openstack.org/api/openstack-image-service/1.1/content/requesting-detailed-metadata-on-public-vm-images.html
|
||||
http://docs.openstack.org/api/openstack-image-service/1.1/content/filtering-images-returned-via-get-images-and-get-imagesdetail.html
|
||||
|
||||
TODO(dtroyer): Implement filtering
|
||||
"""
|
||||
|
||||
url = "/images"
|
||||
if detailed or public or private:
|
||||
# Because we can't all use /details
|
||||
url += "/detail"
|
||||
|
||||
image_list = self.list(url, **filter)['images']
|
||||
|
||||
if public != private:
|
||||
# One is True and one is False, so public represents the filter
|
||||
# state in either case
|
||||
image_list = [i for i in image_list if i['is_public'] == public]
|
||||
|
||||
return image_list
|
69
openstackclient/api/image_v2.py
Normal file
69
openstackclient/api/image_v2.py
Normal file
@ -0,0 +1,69 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Image v2 API Library"""
|
||||
|
||||
from openstackclient.api import image_v1
|
||||
|
||||
|
||||
class APIv2(image_v1.APIv1):
|
||||
"""Image v2 API"""
|
||||
|
||||
def __init__(self, endpoint=None, **kwargs):
|
||||
super(APIv2, self).__init__(endpoint=endpoint, **kwargs)
|
||||
|
||||
# Hack this until discovery is up, and ignore parent endpoint setting
|
||||
self.endpoint = '/'.join([endpoint.rstrip('/'), 'v2'])
|
||||
|
||||
def image_list(
|
||||
self,
|
||||
detailed=False,
|
||||
public=False,
|
||||
private=False,
|
||||
**filter
|
||||
):
|
||||
"""Get available images
|
||||
|
||||
can add limit/marker
|
||||
|
||||
:param detailed:
|
||||
For v1 compatibility only, ignored as v2 is always 'detailed'
|
||||
:param public:
|
||||
Return public images if True
|
||||
:param private:
|
||||
Return private images if True
|
||||
|
||||
If public and private are both True or both False then all images are
|
||||
returned. Both arguments False is equivalent to no filter and all
|
||||
images are returned. Both arguments True is a filter that includes
|
||||
both public and private images which is the same set as all images.
|
||||
|
||||
http://docs.openstack.org/api/openstack-image-service/2.0/content/list-images.html
|
||||
|
||||
TODO(dtroyer): Implement filtering
|
||||
"""
|
||||
|
||||
if public == private:
|
||||
# No filtering for both False and both True cases
|
||||
filter.pop('visibility', None)
|
||||
elif public:
|
||||
filter['visibility'] = 'public'
|
||||
elif private:
|
||||
filter['visibility'] = 'private'
|
||||
|
||||
url = "/images"
|
||||
if detailed:
|
||||
# Because we can't all use /details
|
||||
url += "/detail"
|
||||
|
||||
return self.list(url, **filter)['images']
|
@ -31,9 +31,15 @@ API_VERSIONS = {
|
||||
"2": "glanceclient.v2.client.Client",
|
||||
}
|
||||
|
||||
IMAGE_API_TYPE = 'image'
|
||||
IMAGE_API_VERSIONS = {
|
||||
'1': 'openstackclient.api.image_v1.APIv1',
|
||||
'2': 'openstackclient.api.image_v2.APIv2',
|
||||
}
|
||||
|
||||
|
||||
def make_client(instance):
|
||||
"""Returns an image service client."""
|
||||
"""Returns an image service client"""
|
||||
image_client = utils.get_client_class(
|
||||
API_NAME,
|
||||
instance._api_version[API_NAME],
|
||||
@ -45,13 +51,31 @@ def make_client(instance):
|
||||
region_name=instance._region_name,
|
||||
)
|
||||
|
||||
return image_client(
|
||||
client = image_client(
|
||||
endpoint,
|
||||
token=instance.auth.get_token(instance.session),
|
||||
cacert=instance._cacert,
|
||||
insecure=instance._insecure,
|
||||
)
|
||||
|
||||
# Create the low-level API
|
||||
|
||||
image_api = utils.get_client_class(
|
||||
API_NAME,
|
||||
instance._api_version[API_NAME],
|
||||
IMAGE_API_VERSIONS)
|
||||
LOG.debug('Instantiating image api: %s', image_api)
|
||||
|
||||
client.api = image_api(
|
||||
session=instance.session,
|
||||
endpoint=instance.get_endpoint_for_service_type(
|
||||
IMAGE_API_TYPE,
|
||||
region_name=instance._region_name,
|
||||
)
|
||||
)
|
||||
|
||||
return client
|
||||
|
||||
|
||||
def build_option_parser(parser):
|
||||
"""Hook to add global options"""
|
||||
|
@ -300,6 +300,21 @@ class ListImage(lister.Lister):
|
||||
metavar="<size>",
|
||||
help="Number of images to request in each paginated request",
|
||||
)
|
||||
public_group = parser.add_mutually_exclusive_group()
|
||||
public_group.add_argument(
|
||||
"--public",
|
||||
dest="public",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="List only public images",
|
||||
)
|
||||
public_group.add_argument(
|
||||
"--private",
|
||||
dest="private",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="List only private images",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--long',
|
||||
action='store_true',
|
||||
@ -316,15 +331,21 @@ class ListImage(lister.Lister):
|
||||
kwargs = {}
|
||||
if parsed_args.page_size is not None:
|
||||
kwargs["page_size"] = parsed_args.page_size
|
||||
if parsed_args.public:
|
||||
kwargs['public'] = True
|
||||
if parsed_args.private:
|
||||
kwargs['private'] = True
|
||||
kwargs['detailed'] = parsed_args.long
|
||||
|
||||
data = image_client.images.list(**kwargs)
|
||||
if parsed_args.long:
|
||||
columns = ('ID', 'Name', 'Disk Format', 'Container Format',
|
||||
'Size', 'Status')
|
||||
else:
|
||||
columns = ("ID", "Name")
|
||||
|
||||
return (columns, (utils.get_item_properties(s, columns) for s in data))
|
||||
data = image_client.api.image_list(**kwargs)
|
||||
|
||||
return (columns, (utils.get_dict_properties(s, columns) for s in data))
|
||||
|
||||
|
||||
class SaveImage(command.Command):
|
||||
|
@ -65,6 +65,21 @@ class ListImage(lister.Lister):
|
||||
metavar="<size>",
|
||||
help="Number of images to request in each paginated request",
|
||||
)
|
||||
public_group = parser.add_mutually_exclusive_group()
|
||||
public_group.add_argument(
|
||||
"--public",
|
||||
dest="public",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="List only public images",
|
||||
)
|
||||
public_group.add_argument(
|
||||
"--private",
|
||||
dest="private",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="List only private images",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--long',
|
||||
action='store_true',
|
||||
@ -81,15 +96,21 @@ class ListImage(lister.Lister):
|
||||
kwargs = {}
|
||||
if parsed_args.page_size is not None:
|
||||
kwargs["page_size"] = parsed_args.page_size
|
||||
if parsed_args.public:
|
||||
kwargs['public'] = True
|
||||
if parsed_args.private:
|
||||
kwargs['private'] = True
|
||||
kwargs['detailed'] = parsed_args.long
|
||||
|
||||
data = image_client.images.list(**kwargs)
|
||||
if parsed_args.long:
|
||||
columns = ('ID', 'Name', 'Disk Format', 'Container Format',
|
||||
'Size', 'Status')
|
||||
else:
|
||||
columns = ("ID", "Name")
|
||||
|
||||
return (columns, (utils.get_item_properties(s, columns) for s in data))
|
||||
data = image_client.api.image_list(**kwargs)
|
||||
|
||||
return (columns, (utils.get_dict_properties(s, columns) for s in data))
|
||||
|
||||
|
||||
class SaveImage(command.Command):
|
||||
|
98
openstackclient/tests/api/test_image_v1.py
Normal file
98
openstackclient/tests/api/test_image_v1.py
Normal file
@ -0,0 +1,98 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Image v1 API Library Tests"""
|
||||
|
||||
from requests_mock.contrib import fixture
|
||||
|
||||
from keystoneclient import session
|
||||
from openstackclient.api import image_v1
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
FAKE_PROJECT = 'xyzpdq'
|
||||
FAKE_URL = 'http://gopher.com'
|
||||
|
||||
|
||||
class TestImageAPIv1(utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestImageAPIv1, self).setUp()
|
||||
|
||||
sess = session.Session()
|
||||
self.api = image_v1.APIv1(session=sess, endpoint=FAKE_URL)
|
||||
self.requests_mock = self.useFixture(fixture.Fixture())
|
||||
|
||||
|
||||
class TestImage(TestImageAPIv1):
|
||||
|
||||
PUB_PROT = {
|
||||
'id': '1',
|
||||
'name': 'pub1',
|
||||
'is_public': True,
|
||||
'protected': True,
|
||||
}
|
||||
PUB_NOPROT = {
|
||||
'id': '2',
|
||||
'name': 'pub2-noprot',
|
||||
'is_public': True,
|
||||
'protected': False,
|
||||
}
|
||||
NOPUB_PROT = {
|
||||
'id': '3',
|
||||
'name': 'priv3',
|
||||
'is_public': False,
|
||||
'protected': True,
|
||||
}
|
||||
NOPUB_NOPROT = {
|
||||
'id': '4',
|
||||
'name': 'priv4-noprot',
|
||||
'is_public': False,
|
||||
'protected': False,
|
||||
}
|
||||
LIST_IMAGE_RESP = [
|
||||
PUB_PROT,
|
||||
PUB_NOPROT,
|
||||
NOPUB_PROT,
|
||||
NOPUB_NOPROT,
|
||||
]
|
||||
|
||||
def test_image_list_no_options(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/v1/images',
|
||||
json={'images': self.LIST_IMAGE_RESP},
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.image_list()
|
||||
self.assertEqual(self.LIST_IMAGE_RESP, ret)
|
||||
|
||||
def test_image_list_public(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/v1/images/detail',
|
||||
json={'images': self.LIST_IMAGE_RESP},
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.image_list(public=True)
|
||||
self.assertEqual([self.PUB_PROT, self.PUB_NOPROT], ret)
|
||||
|
||||
def test_image_list_private(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/v1/images/detail',
|
||||
json={'images': self.LIST_IMAGE_RESP},
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.image_list(private=True)
|
||||
self.assertEqual([self.NOPUB_PROT, self.NOPUB_NOPROT], ret)
|
98
openstackclient/tests/api/test_image_v2.py
Normal file
98
openstackclient/tests/api/test_image_v2.py
Normal file
@ -0,0 +1,98 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Image v2 API Library Tests"""
|
||||
|
||||
from requests_mock.contrib import fixture
|
||||
|
||||
from keystoneclient import session
|
||||
from openstackclient.api import image_v2
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
FAKE_PROJECT = 'xyzpdq'
|
||||
FAKE_URL = 'http://gopher.com'
|
||||
|
||||
|
||||
class TestImageAPIv2(utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestImageAPIv2, self).setUp()
|
||||
|
||||
sess = session.Session()
|
||||
self.api = image_v2.APIv2(session=sess, endpoint=FAKE_URL)
|
||||
self.requests_mock = self.useFixture(fixture.Fixture())
|
||||
|
||||
|
||||
class TestImage(TestImageAPIv2):
|
||||
|
||||
PUB_PROT = {
|
||||
'id': '1',
|
||||
'name': 'pub1',
|
||||
'visibility': 'public',
|
||||
'protected': True,
|
||||
}
|
||||
PUB_NOPROT = {
|
||||
'id': '2',
|
||||
'name': 'pub2-noprot',
|
||||
'visibility': 'public',
|
||||
'protected': False,
|
||||
}
|
||||
NOPUB_PROT = {
|
||||
'id': '3',
|
||||
'name': 'priv3',
|
||||
'visibility': 'private',
|
||||
'protected': True,
|
||||
}
|
||||
NOPUB_NOPROT = {
|
||||
'id': '4',
|
||||
'name': 'priv4-noprot',
|
||||
'visibility': 'private',
|
||||
'protected': False,
|
||||
}
|
||||
LIST_IMAGE_RESP = [
|
||||
PUB_PROT,
|
||||
PUB_NOPROT,
|
||||
NOPUB_PROT,
|
||||
NOPUB_NOPROT,
|
||||
]
|
||||
|
||||
def test_image_list_no_options(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/v2/images',
|
||||
json={'images': self.LIST_IMAGE_RESP},
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.image_list()
|
||||
self.assertEqual(self.LIST_IMAGE_RESP, ret)
|
||||
|
||||
def test_image_list_public(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/v2/images',
|
||||
json={'images': [self.PUB_PROT, self.PUB_NOPROT]},
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.image_list(public=True)
|
||||
self.assertEqual([self.PUB_PROT, self.PUB_NOPROT], ret)
|
||||
|
||||
def test_image_list_private(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/v2/images',
|
||||
json={'images': [self.NOPUB_PROT, self.NOPUB_NOPROT]},
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.image_list(public=True)
|
||||
self.assertEqual([self.NOPUB_PROT, self.NOPUB_NOPROT], ret)
|
@ -300,6 +300,128 @@ class TestImageDelete(TestImage):
|
||||
)
|
||||
|
||||
|
||||
class TestImageList(TestImage):
|
||||
|
||||
def setUp(self):
|
||||
super(TestImageList, self).setUp()
|
||||
|
||||
self.api_mock = mock.Mock()
|
||||
self.api_mock.image_list.return_value = [
|
||||
copy.deepcopy(image_fakes.IMAGE),
|
||||
]
|
||||
self.app.client_manager.image.api = self.api_mock
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = image.ListImage(self.app, None)
|
||||
|
||||
def test_image_list_no_options(self):
|
||||
arglist = []
|
||||
verifylist = [
|
||||
('public', False),
|
||||
('private', False),
|
||||
('long', False),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.api_mock.image_list.assert_called_with(
|
||||
detailed=False,
|
||||
)
|
||||
|
||||
collist = ('ID', 'Name')
|
||||
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = ((
|
||||
image_fakes.image_id,
|
||||
image_fakes.image_name,
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_image_list_public_option(self):
|
||||
arglist = [
|
||||
'--public',
|
||||
]
|
||||
verifylist = [
|
||||
('public', True),
|
||||
('private', False),
|
||||
('long', False),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.api_mock.image_list.assert_called_with(
|
||||
detailed=False,
|
||||
public=True,
|
||||
)
|
||||
|
||||
collist = ('ID', 'Name')
|
||||
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = ((
|
||||
image_fakes.image_id,
|
||||
image_fakes.image_name,
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_image_list_private_option(self):
|
||||
arglist = [
|
||||
'--private',
|
||||
]
|
||||
verifylist = [
|
||||
('public', False),
|
||||
('private', True),
|
||||
('long', False),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.api_mock.image_list.assert_called_with(
|
||||
detailed=False,
|
||||
private=True,
|
||||
)
|
||||
|
||||
collist = ('ID', 'Name')
|
||||
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = ((
|
||||
image_fakes.image_id,
|
||||
image_fakes.image_name,
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_image_list_long_option(self):
|
||||
arglist = [
|
||||
'--long',
|
||||
]
|
||||
verifylist = [
|
||||
('long', True),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.api_mock.image_list.assert_called_with(
|
||||
detailed=True,
|
||||
)
|
||||
|
||||
collist = ('ID', 'Name', 'Disk Format', 'Container Format',
|
||||
'Size', 'Status')
|
||||
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = ((
|
||||
image_fakes.image_id,
|
||||
image_fakes.image_name,
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
|
||||
class TestImageSet(TestImage):
|
||||
|
||||
def setUp(self):
|
||||
@ -453,48 +575,3 @@ class TestImageSet(TestImage):
|
||||
image_fakes.image_id,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
||||
class TestImageList(TestImage):
|
||||
|
||||
def setUp(self):
|
||||
super(TestImageList, self).setUp()
|
||||
|
||||
# This is the return value for utils.find_resource()
|
||||
self.images_mock.list.return_value = [
|
||||
fakes.FakeResource(
|
||||
None,
|
||||
copy.deepcopy(image_fakes.IMAGE),
|
||||
loaded=True,
|
||||
),
|
||||
]
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = image.ListImage(self.app, None)
|
||||
|
||||
def test_image_list_long_option(self):
|
||||
arglist = [
|
||||
'--long',
|
||||
]
|
||||
verifylist = [
|
||||
('long', True),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.images_mock.list.assert_called_with()
|
||||
|
||||
collist = ('ID', 'Name', 'Disk Format', 'Container Format',
|
||||
'Size', 'Status')
|
||||
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = ((
|
||||
image_fakes.image_id,
|
||||
image_fakes.image_name,
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
@ -14,6 +14,7 @@
|
||||
#
|
||||
|
||||
import copy
|
||||
import mock
|
||||
|
||||
from openstackclient.image.v2 import image
|
||||
from openstackclient.tests import fakes
|
||||
@ -68,18 +69,93 @@ class TestImageList(TestImage):
|
||||
def setUp(self):
|
||||
super(TestImageList, self).setUp()
|
||||
|
||||
# This is the return value for utils.find_resource()
|
||||
self.images_mock.list.return_value = [
|
||||
fakes.FakeResource(
|
||||
None,
|
||||
self.api_mock = mock.Mock()
|
||||
self.api_mock.image_list.return_value = [
|
||||
copy.deepcopy(image_fakes.IMAGE),
|
||||
loaded=True,
|
||||
),
|
||||
]
|
||||
self.app.client_manager.image.api = self.api_mock
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = image.ListImage(self.app, None)
|
||||
|
||||
def test_image_list_no_options(self):
|
||||
arglist = []
|
||||
verifylist = [
|
||||
('public', False),
|
||||
('private', False),
|
||||
('long', False),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.api_mock.image_list.assert_called_with(
|
||||
detailed=False,
|
||||
)
|
||||
|
||||
collist = ('ID', 'Name')
|
||||
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = ((
|
||||
image_fakes.image_id,
|
||||
image_fakes.image_name,
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_image_list_public_option(self):
|
||||
arglist = [
|
||||
'--public',
|
||||
]
|
||||
verifylist = [
|
||||
('public', True),
|
||||
('private', False),
|
||||
('long', False),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.api_mock.image_list.assert_called_with(
|
||||
detailed=False,
|
||||
public=True,
|
||||
)
|
||||
|
||||
collist = ('ID', 'Name')
|
||||
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = ((
|
||||
image_fakes.image_id,
|
||||
image_fakes.image_name,
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_image_list_private_option(self):
|
||||
arglist = [
|
||||
'--private',
|
||||
]
|
||||
verifylist = [
|
||||
('public', False),
|
||||
('private', True),
|
||||
('long', False),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.api_mock.image_list.assert_called_with(
|
||||
detailed=False,
|
||||
private=True,
|
||||
)
|
||||
|
||||
collist = ('ID', 'Name')
|
||||
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = ((
|
||||
image_fakes.image_id,
|
||||
image_fakes.image_name,
|
||||
), )
|
||||
self.assertEqual(datalist, tuple(data))
|
||||
|
||||
def test_image_list_long_option(self):
|
||||
arglist = [
|
||||
'--long',
|
||||
@ -91,7 +167,9 @@ class TestImageList(TestImage):
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
self.images_mock.list.assert_called_with()
|
||||
self.api_mock.image_list.assert_called_with(
|
||||
detailed=True,
|
||||
)
|
||||
|
||||
collist = ('ID', 'Name', 'Disk Format', 'Container Format',
|
||||
'Size', 'Status')
|
||||
|
Loading…
Reference in New Issue
Block a user