Move object-store commands to low-level API
api.object_store.APIv1 now contains the formerly top-level functions implementing the object-store REST client. This replaces the old-style ObjectClientv1 that is no longer necessary. Change-Id: I7d8fea326b214481e7d6b24119bd41777c6aa968
This commit is contained in:
parent
e3b9b96588
commit
31018bf7c2
381
openstackclient/api/object_store_v1.py
Normal file
381
openstackclient/api/object_store_v1.py
Normal file
@ -0,0 +1,381 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Object Store v1 API Library"""
|
||||
|
||||
import os
|
||||
import six
|
||||
|
||||
try:
|
||||
from urllib.parse import urlparse # noqa
|
||||
except ImportError:
|
||||
from urlparse import urlparse # noqa
|
||||
|
||||
from openstackclient.api import api
|
||||
|
||||
|
||||
class APIv1(api.BaseAPI):
|
||||
"""Object Store v1 API"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super(APIv1, self).__init__(**kwargs)
|
||||
|
||||
def container_create(
|
||||
self,
|
||||
container=None,
|
||||
):
|
||||
"""Create a container
|
||||
|
||||
:param string container:
|
||||
name of container to create
|
||||
:returns:
|
||||
dict of returned headers
|
||||
"""
|
||||
|
||||
response = self.create(container, method='PUT')
|
||||
url_parts = urlparse(self.endpoint)
|
||||
data = {
|
||||
'account': url_parts.path.split('/')[-1],
|
||||
'container': container,
|
||||
'x-trans-id': response.headers.get('x-trans-id', None),
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
def container_delete(
|
||||
self,
|
||||
container=None,
|
||||
):
|
||||
"""Delete a container
|
||||
|
||||
:param string container:
|
||||
name of container to delete
|
||||
"""
|
||||
|
||||
if container:
|
||||
self.delete(container)
|
||||
|
||||
def container_list(
|
||||
self,
|
||||
all_data=False,
|
||||
limit=None,
|
||||
marker=None,
|
||||
end_marker=None,
|
||||
prefix=None,
|
||||
**params
|
||||
):
|
||||
"""Get containers in an account
|
||||
|
||||
:param boolean all_data:
|
||||
if True, return a full listing, else returns a max of
|
||||
10000 listings
|
||||
:param integer limit:
|
||||
query return count limit
|
||||
:param string marker:
|
||||
query marker
|
||||
:param string end_marker:
|
||||
query end_marker
|
||||
:param string prefix:
|
||||
query prefix
|
||||
:returns:
|
||||
list of container names
|
||||
"""
|
||||
|
||||
params['format'] = 'json'
|
||||
|
||||
if all_data:
|
||||
data = listing = self.container_list(
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
end_marker=end_marker,
|
||||
prefix=prefix,
|
||||
**params
|
||||
)
|
||||
while listing:
|
||||
marker = listing[-1]['name']
|
||||
listing = self.container_list(
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
end_marker=end_marker,
|
||||
prefix=prefix,
|
||||
**params
|
||||
)
|
||||
if listing:
|
||||
data.extend(listing)
|
||||
return data
|
||||
|
||||
if limit:
|
||||
params['limit'] = limit
|
||||
if marker:
|
||||
params['marker'] = marker
|
||||
if end_marker:
|
||||
params['end_marker'] = end_marker
|
||||
if prefix:
|
||||
params['prefix'] = prefix
|
||||
|
||||
return self.list('', **params)
|
||||
|
||||
def container_save(
|
||||
self,
|
||||
container=None,
|
||||
):
|
||||
"""Save all the content from a container
|
||||
|
||||
:param string container:
|
||||
name of container to save
|
||||
"""
|
||||
|
||||
objects = self.object_list(container=container)
|
||||
for object in objects:
|
||||
self.object_save(container=container, object=object['name'])
|
||||
|
||||
def container_show(
|
||||
self,
|
||||
container=None,
|
||||
):
|
||||
"""Get container details
|
||||
|
||||
:param string container:
|
||||
name of container to show
|
||||
:returns:
|
||||
dict of returned headers
|
||||
"""
|
||||
|
||||
response = self._request('HEAD', container)
|
||||
data = {
|
||||
'account': response.headers.get('x-container-meta-owner', None),
|
||||
'container': container,
|
||||
'object_count': response.headers.get(
|
||||
'x-container-object-count',
|
||||
None,
|
||||
),
|
||||
'bytes_used': response.headers.get('x-container-bytes-used', None),
|
||||
'read_acl': response.headers.get('x-container-read', None),
|
||||
'write_acl': response.headers.get('x-container-write', None),
|
||||
'sync_to': response.headers.get('x-container-sync-to', None),
|
||||
'sync_key': response.headers.get('x-container-sync-key', None),
|
||||
}
|
||||
return data
|
||||
|
||||
def object_create(
|
||||
self,
|
||||
container=None,
|
||||
object=None,
|
||||
):
|
||||
"""Create an object inside a container
|
||||
|
||||
:param string container:
|
||||
name of container to store object
|
||||
:param string object:
|
||||
local path to object
|
||||
:returns:
|
||||
dict of returned headers
|
||||
"""
|
||||
|
||||
if container is None or object is None:
|
||||
# TODO(dtroyer): What exception to raise here?
|
||||
return {}
|
||||
|
||||
full_url = "%s/%s" % (container, object)
|
||||
response = self.create(full_url, method='PUT', data=open(object))
|
||||
url_parts = urlparse(self.endpoint)
|
||||
data = {
|
||||
'account': url_parts.path.split('/')[-1],
|
||||
'container': container,
|
||||
'object': object,
|
||||
'x-trans-id': response.headers.get('X-Trans-Id', None),
|
||||
'etag': response.headers.get('Etag', None),
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
def object_delete(
|
||||
self,
|
||||
container=None,
|
||||
object=None,
|
||||
):
|
||||
"""Delete an object from a container
|
||||
|
||||
:param string container:
|
||||
name of container that stores object
|
||||
:param string object:
|
||||
name of object to delete
|
||||
"""
|
||||
|
||||
if container is None or object is None:
|
||||
return
|
||||
|
||||
self.delete("%s/%s" % (container, object))
|
||||
|
||||
def object_list(
|
||||
self,
|
||||
container=None,
|
||||
all_data=False,
|
||||
limit=None,
|
||||
marker=None,
|
||||
end_marker=None,
|
||||
delimiter=None,
|
||||
prefix=None,
|
||||
**params
|
||||
):
|
||||
"""List objects in a container
|
||||
|
||||
:param string container:
|
||||
container name to get a listing for
|
||||
:param boolean all_data:
|
||||
if True, return a full listing, else returns a max of
|
||||
10000 listings
|
||||
:param integer limit:
|
||||
query return count limit
|
||||
:param string marker:
|
||||
query marker
|
||||
:param string end_marker:
|
||||
query end_marker
|
||||
:param string prefix:
|
||||
query prefix
|
||||
:param string delimiter:
|
||||
string to delimit the queries on
|
||||
:returns: a tuple of (response headers, a list of objects) The response
|
||||
headers will be a dict and all header names will be lowercase.
|
||||
"""
|
||||
|
||||
if container is None or object is None:
|
||||
return None
|
||||
|
||||
if all_data:
|
||||
data = listing = self.object_list(
|
||||
container=container,
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
end_marker=end_marker,
|
||||
prefix=prefix,
|
||||
delimiter=delimiter,
|
||||
**params
|
||||
)
|
||||
while listing:
|
||||
if delimiter:
|
||||
marker = listing[-1].get('name', listing[-1].get('subdir'))
|
||||
else:
|
||||
marker = listing[-1]['name']
|
||||
listing = self.object_list(
|
||||
container=container,
|
||||
limit=limit,
|
||||
marker=marker,
|
||||
end_marker=end_marker,
|
||||
prefix=prefix,
|
||||
delimiter=delimiter,
|
||||
**params
|
||||
)
|
||||
if listing:
|
||||
data.extend(listing)
|
||||
return data
|
||||
|
||||
params = {}
|
||||
if limit:
|
||||
params['limit'] = limit
|
||||
if marker:
|
||||
params['marker'] = marker
|
||||
if end_marker:
|
||||
params['end_marker'] = end_marker
|
||||
if prefix:
|
||||
params['prefix'] = prefix
|
||||
if delimiter:
|
||||
params['delimiter'] = delimiter
|
||||
|
||||
return self.list(container, **params)
|
||||
|
||||
def object_save(
|
||||
self,
|
||||
container=None,
|
||||
object=None,
|
||||
file=None,
|
||||
):
|
||||
"""Save an object stored in a container
|
||||
|
||||
:param string container:
|
||||
name of container that stores object
|
||||
:param string object:
|
||||
name of object to save
|
||||
:param string file:
|
||||
local name of object
|
||||
"""
|
||||
|
||||
if not file:
|
||||
file = object
|
||||
|
||||
response = self._request(
|
||||
'GET',
|
||||
"%s/%s" % (container, object),
|
||||
stream=True,
|
||||
)
|
||||
if response.status_code == 200:
|
||||
if not os.path.exists(os.path.dirname(file)):
|
||||
os.makedirs(os.path.dirname(file))
|
||||
with open(file, 'wb') as f:
|
||||
for chunk in response.iter_content():
|
||||
f.write(chunk)
|
||||
|
||||
def object_show(
|
||||
self,
|
||||
container=None,
|
||||
object=None,
|
||||
):
|
||||
"""Get object details
|
||||
|
||||
:param string container:
|
||||
container name for object to get
|
||||
:param string object:
|
||||
name of object to get
|
||||
:returns:
|
||||
dict of object properties
|
||||
"""
|
||||
|
||||
if container is None or object is None:
|
||||
return {}
|
||||
|
||||
response = self._request('HEAD', "%s/%s" % (container, object))
|
||||
data = {
|
||||
'account': response.headers.get('x-container-meta-owner', None),
|
||||
'container': container,
|
||||
'object': object,
|
||||
'content-type': response.headers.get('content-type', None),
|
||||
}
|
||||
if 'content-length' in response.headers:
|
||||
data['content-length'] = response.headers.get(
|
||||
'content-length',
|
||||
None,
|
||||
)
|
||||
if 'last-modified' in response.headers:
|
||||
data['last-modified'] = response.headers.get('last-modified', None)
|
||||
if 'etag' in response.headers:
|
||||
data['etag'] = response.headers.get('etag', None)
|
||||
if 'x-object-manifest' in response.headers:
|
||||
data['x-object-manifest'] = response.headers.get(
|
||||
'x-object-manifest',
|
||||
None,
|
||||
)
|
||||
for key, value in six.iteritems(response.headers):
|
||||
if key.startswith('x-object-meta-'):
|
||||
data[key[len('x-object-meta-'):].lower()] = value
|
||||
elif key not in (
|
||||
'content-type',
|
||||
'content-length',
|
||||
'last-modified',
|
||||
'etag',
|
||||
'date',
|
||||
'x-object-manifest',
|
||||
'x-container-meta-owner',
|
||||
):
|
||||
data[key.lower()] = value
|
||||
|
||||
return data
|
@ -17,6 +17,7 @@
|
||||
|
||||
import logging
|
||||
|
||||
from openstackclient.api import object_store_v1
|
||||
from openstackclient.common import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -30,7 +31,7 @@ API_VERSIONS = {
|
||||
|
||||
|
||||
def make_client(instance):
|
||||
"""Returns an object service client."""
|
||||
"""Returns an object-store API client."""
|
||||
|
||||
object_client = utils.get_client_class(
|
||||
API_NAME,
|
||||
@ -42,9 +43,11 @@ def make_client(instance):
|
||||
endpoint = instance._url
|
||||
else:
|
||||
endpoint = instance.get_endpoint_for_service_type("object-store")
|
||||
client = object_client(
|
||||
|
||||
client = object_store_v1.APIv1(
|
||||
session=instance.session,
|
||||
service_type='object-store',
|
||||
endpoint=endpoint,
|
||||
token=instance._token,
|
||||
)
|
||||
return client
|
||||
|
||||
@ -61,16 +64,3 @@ def build_option_parser(parser):
|
||||
DEFAULT_OBJECT_API_VERSION +
|
||||
' (Env: OS_OBJECT_API_VERSION)')
|
||||
return parser
|
||||
|
||||
|
||||
class ObjectClientv1(object):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
endpoint_type='publicURL',
|
||||
endpoint=None,
|
||||
token=None,
|
||||
):
|
||||
self.endpoint_type = endpoint_type
|
||||
self.endpoint = endpoint
|
||||
self.token = token
|
||||
|
@ -24,7 +24,6 @@ from cliff import lister
|
||||
from cliff import show
|
||||
|
||||
from openstackclient.common import utils
|
||||
from openstackclient.object.v1.lib import container as lib_container
|
||||
|
||||
|
||||
class CreateContainer(lister.Lister):
|
||||
@ -47,10 +46,8 @@ class CreateContainer(lister.Lister):
|
||||
|
||||
results = []
|
||||
for container in parsed_args.containers:
|
||||
data = lib_container.create_container(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
container,
|
||||
data = self.app.client_manager.object_store.container_create(
|
||||
container=container,
|
||||
)
|
||||
results.append(data)
|
||||
|
||||
@ -81,10 +78,8 @@ class DeleteContainer(command.Command):
|
||||
self.log.debug('take_action(%s)', parsed_args)
|
||||
|
||||
for container in parsed_args.containers:
|
||||
lib_container.delete_container(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
container,
|
||||
self.app.client_manager.object_store.container_delete(
|
||||
container=container,
|
||||
)
|
||||
|
||||
|
||||
@ -150,9 +145,7 @@ class ListContainer(lister.Lister):
|
||||
if parsed_args.all:
|
||||
kwargs['full_listing'] = True
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
data = self.app.client_manager.object_store.container_list(
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -180,10 +173,8 @@ class SaveContainer(command.Command):
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)", parsed_args)
|
||||
|
||||
lib_container.save_container(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
parsed_args.container
|
||||
self.app.client_manager.object_store.container_save(
|
||||
container=parsed_args.container,
|
||||
)
|
||||
|
||||
|
||||
@ -204,10 +195,8 @@ class ShowContainer(show.ShowOne):
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug('take_action(%s)', parsed_args)
|
||||
|
||||
data = lib_container.show_container(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
parsed_args.container,
|
||||
data = self.app.client_manager.object_store.container_show(
|
||||
container=parsed_args.container,
|
||||
)
|
||||
|
||||
return zip(*sorted(six.iteritems(data)))
|
||||
|
@ -1,170 +0,0 @@
|
||||
# Copyright 2010-2012 OpenStack Foundation
|
||||
# Copyright 2013 Nebula Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Object v1 API library"""
|
||||
|
||||
try:
|
||||
from urllib.parse import urlparse # noqa
|
||||
except ImportError:
|
||||
from urlparse import urlparse # noqa
|
||||
|
||||
from openstackclient.object.v1.lib import object as object_lib
|
||||
|
||||
|
||||
def create_container(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
):
|
||||
"""Create a container
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: name of container to create
|
||||
:returns: dict of returned headers
|
||||
"""
|
||||
|
||||
response = session.put("%s/%s" % (url, container))
|
||||
url_parts = urlparse(url)
|
||||
data = {
|
||||
'account': url_parts.path.split('/')[-1],
|
||||
'container': container,
|
||||
'x-trans-id': response.headers.get('x-trans-id', None),
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def delete_container(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
):
|
||||
"""Delete a container
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: name of container to delete
|
||||
"""
|
||||
|
||||
session.delete("%s/%s" % (url, container))
|
||||
|
||||
|
||||
def list_containers(
|
||||
session,
|
||||
url,
|
||||
marker=None,
|
||||
limit=None,
|
||||
end_marker=None,
|
||||
prefix=None,
|
||||
full_listing=False,
|
||||
):
|
||||
"""Get containers in an account
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param marker: marker query
|
||||
:param limit: limit query
|
||||
:param end_marker: end_marker query
|
||||
:param prefix: prefix query
|
||||
:param full_listing: if True, return a full listing, else returns a max
|
||||
of 10000 listings
|
||||
:returns: list of containers
|
||||
"""
|
||||
|
||||
if full_listing:
|
||||
data = listing = list_containers(
|
||||
session,
|
||||
url,
|
||||
marker,
|
||||
limit,
|
||||
end_marker,
|
||||
prefix,
|
||||
)
|
||||
while listing:
|
||||
marker = listing[-1]['name']
|
||||
listing = list_containers(
|
||||
session,
|
||||
url,
|
||||
marker,
|
||||
limit,
|
||||
end_marker,
|
||||
prefix,
|
||||
)
|
||||
if listing:
|
||||
data.extend(listing)
|
||||
return data
|
||||
|
||||
params = {
|
||||
'format': 'json',
|
||||
}
|
||||
if marker:
|
||||
params['marker'] = marker
|
||||
if limit:
|
||||
params['limit'] = limit
|
||||
if end_marker:
|
||||
params['end_marker'] = end_marker
|
||||
if prefix:
|
||||
params['prefix'] = prefix
|
||||
return session.get(url, params=params).json()
|
||||
|
||||
|
||||
def save_container(
|
||||
session,
|
||||
url,
|
||||
container
|
||||
):
|
||||
"""Save all the content from a container
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: name of container to save
|
||||
"""
|
||||
|
||||
objects = object_lib.list_objects(session, url, container)
|
||||
for object in objects:
|
||||
object_lib.save_object(session, url, container, object['name'])
|
||||
|
||||
|
||||
def show_container(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
):
|
||||
"""Get container details
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: name of container to show
|
||||
:returns: dict of returned headers
|
||||
"""
|
||||
|
||||
response = session.head("%s/%s" % (url, container))
|
||||
data = {
|
||||
'account': response.headers.get('x-container-meta-owner', None),
|
||||
'container': container,
|
||||
'object_count': response.headers.get(
|
||||
'x-container-object-count',
|
||||
None,
|
||||
),
|
||||
'bytes_used': response.headers.get('x-container-bytes-used', None),
|
||||
'read_acl': response.headers.get('x-container-read', None),
|
||||
'write_acl': response.headers.get('x-container-write', None),
|
||||
'sync_to': response.headers.get('x-container-sync-to', None),
|
||||
'sync_key': response.headers.get('x-container-sync-key', None),
|
||||
}
|
||||
|
||||
return data
|
@ -1,221 +0,0 @@
|
||||
# Copyright 2010-2012 OpenStack Foundation
|
||||
# Copyright 2013 Nebula Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Object v1 API library"""
|
||||
|
||||
import os
|
||||
|
||||
import six
|
||||
|
||||
try:
|
||||
from urllib.parse import urlparse # noqa
|
||||
except ImportError:
|
||||
from urlparse import urlparse # noqa
|
||||
|
||||
|
||||
def create_object(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
object,
|
||||
):
|
||||
"""Create an object, upload it to a container
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: name of container to store object
|
||||
:param object: local path to object
|
||||
:returns: dict of returned headers
|
||||
"""
|
||||
|
||||
full_url = "%s/%s/%s" % (url, container, object)
|
||||
response = session.put(full_url, data=open(object))
|
||||
url_parts = urlparse(url)
|
||||
data = {
|
||||
'account': url_parts.path.split('/')[-1],
|
||||
'container': container,
|
||||
'object': object,
|
||||
'x-trans-id': response.headers.get('X-Trans-Id', None),
|
||||
'etag': response.headers.get('Etag', None),
|
||||
}
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def delete_object(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
object,
|
||||
):
|
||||
"""Delete an object stored in a container
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: name of container that stores object
|
||||
:param container: name of object to delete
|
||||
"""
|
||||
|
||||
session.delete("%s/%s/%s" % (url, container, object))
|
||||
|
||||
|
||||
def list_objects(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
marker=None,
|
||||
limit=None,
|
||||
end_marker=None,
|
||||
delimiter=None,
|
||||
prefix=None,
|
||||
path=None,
|
||||
full_listing=False,
|
||||
):
|
||||
"""Get objects in a container
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: container name to get a listing for
|
||||
:param marker: marker query
|
||||
:param limit: limit query
|
||||
:param end_marker: marker query
|
||||
:param delimiter: string to delimit the queries on
|
||||
:param prefix: prefix query
|
||||
:param path: path query (equivalent: "delimiter=/" and "prefix=path/")
|
||||
:param full_listing: if True, return a full listing, else returns a max
|
||||
of 10000 listings
|
||||
:returns: a tuple of (response headers, a list of objects) The response
|
||||
headers will be a dict and all header names will be lowercase.
|
||||
"""
|
||||
|
||||
if full_listing:
|
||||
data = listing = list_objects(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
marker,
|
||||
limit,
|
||||
end_marker,
|
||||
delimiter,
|
||||
prefix,
|
||||
path,
|
||||
)
|
||||
while listing:
|
||||
if delimiter:
|
||||
marker = listing[-1].get('name', listing[-1].get('subdir'))
|
||||
else:
|
||||
marker = listing[-1]['name']
|
||||
listing = list_objects(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
marker,
|
||||
limit,
|
||||
end_marker,
|
||||
delimiter,
|
||||
prefix,
|
||||
path,
|
||||
)
|
||||
if listing:
|
||||
data.extend(listing)
|
||||
return data
|
||||
|
||||
params = {
|
||||
'format': 'json',
|
||||
}
|
||||
if marker:
|
||||
params['marker'] = marker
|
||||
if limit:
|
||||
params['limit'] = limit
|
||||
if end_marker:
|
||||
params['end_marker'] = end_marker
|
||||
if delimiter:
|
||||
params['delimiter'] = delimiter
|
||||
if prefix:
|
||||
params['prefix'] = prefix
|
||||
if path:
|
||||
params['path'] = path
|
||||
requrl = "%s/%s" % (url, container)
|
||||
return session.get(requrl, params=params).json()
|
||||
|
||||
|
||||
def save_object(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
obj,
|
||||
file=None
|
||||
):
|
||||
"""Save an object stored in a container
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: name of container that stores object
|
||||
:param object: name of object to save
|
||||
:param file: local name of object
|
||||
"""
|
||||
|
||||
if not file:
|
||||
file = obj
|
||||
|
||||
response = session.get("%s/%s/%s" % (url, container, obj), stream=True)
|
||||
if response.status_code == 200:
|
||||
if not os.path.exists(os.path.dirname(file)):
|
||||
os.makedirs(os.path.dirname(file))
|
||||
with open(file, 'wb') as f:
|
||||
for chunk in response.iter_content():
|
||||
f.write(chunk)
|
||||
|
||||
|
||||
def show_object(
|
||||
session,
|
||||
url,
|
||||
container,
|
||||
obj,
|
||||
):
|
||||
"""Get object details
|
||||
|
||||
:param session: an authenticated keystoneclient.session.Session object
|
||||
:param url: endpoint
|
||||
:param container: container name to get a listing for
|
||||
:returns: dict of object properties
|
||||
"""
|
||||
|
||||
response = session.head("%s/%s/%s" % (url, container, obj))
|
||||
data = {
|
||||
'account': response.headers.get('x-container-meta-owner', None),
|
||||
'container': container,
|
||||
'object': obj,
|
||||
'content-type': response.headers.get('content-type', None),
|
||||
}
|
||||
if 'content-length' in response.headers:
|
||||
data['content-length'] = response.headers.get('content-length', None)
|
||||
if 'last-modified' in response.headers:
|
||||
data['last-modified'] = response.headers.get('last-modified', None)
|
||||
if 'etag' in response.headers:
|
||||
data['etag'] = response.headers.get('etag', None)
|
||||
if 'x-object-manifest' in response.headers:
|
||||
data['x-object-manifest'] = response.headers.get(
|
||||
'x-object-manifest', None)
|
||||
for key, value in six.iteritems(response.headers):
|
||||
if key.startswith('x-object-meta-'):
|
||||
data[key[len('x-object-meta-'):].lower()] = value
|
||||
elif key not in (
|
||||
'content-type', 'content-length', 'last-modified',
|
||||
'etag', 'date', 'x-object-manifest', 'x-container-meta-owner'):
|
||||
data[key.lower()] = value
|
||||
|
||||
return data
|
@ -24,7 +24,6 @@ from cliff import lister
|
||||
from cliff import show
|
||||
|
||||
from openstackclient.common import utils
|
||||
from openstackclient.object.v1.lib import object as lib_object
|
||||
|
||||
|
||||
class CreateObject(lister.Lister):
|
||||
@ -52,11 +51,9 @@ class CreateObject(lister.Lister):
|
||||
|
||||
results = []
|
||||
for obj in parsed_args.objects:
|
||||
data = lib_object.create_object(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
parsed_args.container,
|
||||
obj,
|
||||
data = self.app.client_manager.object_store.object_create(
|
||||
container=parsed_args.container,
|
||||
object=obj,
|
||||
)
|
||||
results.append(data)
|
||||
|
||||
@ -92,12 +89,9 @@ class DeleteObject(command.Command):
|
||||
self.log.debug('take_action(%s)', parsed_args)
|
||||
|
||||
for obj in parsed_args.objects:
|
||||
lib_object.delete_object(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
parsed_args.container,
|
||||
obj,
|
||||
self.app.client_manager.object_store.object_delete(
|
||||
container=parsed_args.container,
|
||||
object=obj,
|
||||
)
|
||||
|
||||
|
||||
@ -181,10 +175,8 @@ class ListObject(lister.Lister):
|
||||
if parsed_args.all:
|
||||
kwargs['full_listing'] = True
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
parsed_args.container,
|
||||
data = self.app.client_manager.object_store.object_list(
|
||||
container=parsed_args.container,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -222,12 +214,10 @@ class SaveObject(command.Command):
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug("take_action(%s)", parsed_args)
|
||||
|
||||
lib_object.save_object(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
parsed_args.container,
|
||||
parsed_args.object,
|
||||
parsed_args.file,
|
||||
self.app.client_manager.object_store.object_save(
|
||||
container=parsed_args.container,
|
||||
object=parsed_args.object,
|
||||
file=parsed_args.file,
|
||||
)
|
||||
|
||||
|
||||
@ -253,11 +243,9 @@ class ShowObject(show.ShowOne):
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug('take_action(%s)', parsed_args)
|
||||
|
||||
data = lib_object.show_object(
|
||||
self.app.client_manager.session,
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
parsed_args.container,
|
||||
parsed_args.object,
|
||||
data = self.app.client_manager.object_store.object_show(
|
||||
container=parsed_args.container,
|
||||
object=parsed_args.object,
|
||||
)
|
||||
|
||||
return zip(*sorted(six.iteritems(data)))
|
||||
|
326
openstackclient/tests/api/test_object_store_v1.py
Normal file
326
openstackclient/tests/api/test_object_store_v1.py
Normal file
@ -0,0 +1,326 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Object Store v1 API Library Tests"""
|
||||
|
||||
from requests_mock.contrib import fixture
|
||||
|
||||
from keystoneclient import session
|
||||
from openstackclient.api import object_store_v1 as object_store
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
FAKE_ACCOUNT = 'q12we34r'
|
||||
FAKE_AUTH = '11223344556677889900'
|
||||
FAKE_URL = 'http://gopher.com/v1/' + FAKE_ACCOUNT
|
||||
|
||||
FAKE_CONTAINER = 'rainbarrel'
|
||||
FAKE_OBJECT = 'spigot'
|
||||
|
||||
LIST_CONTAINER_RESP = [
|
||||
'qaz',
|
||||
'fred',
|
||||
]
|
||||
|
||||
LIST_OBJECT_RESP = [
|
||||
{'name': 'fred', 'bytes': 1234, 'content_type': 'text'},
|
||||
{'name': 'wilma', 'bytes': 5678, 'content_type': 'text'},
|
||||
]
|
||||
|
||||
|
||||
class TestObjectAPIv1(utils.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestObjectAPIv1, self).setUp()
|
||||
sess = session.Session()
|
||||
self.api = object_store.APIv1(session=sess, endpoint=FAKE_URL)
|
||||
self.requests_mock = self.useFixture(fixture.Fixture())
|
||||
|
||||
|
||||
class TestContainer(TestObjectAPIv1):
|
||||
|
||||
def setUp(self):
|
||||
super(TestContainer, self).setUp()
|
||||
|
||||
def test_container_create(self):
|
||||
headers = {
|
||||
'x-trans-id': '1qaz2wsx',
|
||||
}
|
||||
self.requests_mock.register_uri(
|
||||
'PUT',
|
||||
FAKE_URL + '/qaz',
|
||||
headers=headers,
|
||||
status_code=201,
|
||||
)
|
||||
ret = self.api.container_create(container='qaz')
|
||||
data = {
|
||||
'account': FAKE_ACCOUNT,
|
||||
'container': 'qaz',
|
||||
'x-trans-id': '1qaz2wsx',
|
||||
}
|
||||
self.assertEqual(data, ret)
|
||||
|
||||
def test_container_delete(self):
|
||||
self.requests_mock.register_uri(
|
||||
'DELETE',
|
||||
FAKE_URL + '/qaz',
|
||||
status_code=204,
|
||||
)
|
||||
ret = self.api.container_delete(container='qaz')
|
||||
self.assertIsNone(ret)
|
||||
|
||||
def test_container_list_no_options(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL,
|
||||
json=LIST_CONTAINER_RESP,
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.container_list()
|
||||
self.assertEqual(LIST_CONTAINER_RESP, ret)
|
||||
|
||||
def test_container_list_prefix(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '?prefix=foo%2f&format=json',
|
||||
json=LIST_CONTAINER_RESP,
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.container_list(
|
||||
prefix='foo/',
|
||||
)
|
||||
self.assertEqual(LIST_CONTAINER_RESP, ret)
|
||||
|
||||
def test_container_list_marker_limit_end(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '?marker=next&limit=2&end_marker=stop&format=json',
|
||||
json=LIST_CONTAINER_RESP,
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.container_list(
|
||||
marker='next',
|
||||
limit=2,
|
||||
end_marker='stop',
|
||||
)
|
||||
self.assertEqual(LIST_CONTAINER_RESP, ret)
|
||||
|
||||
# def test_container_list_full_listing(self):
|
||||
# sess = self.app.client_manager.session
|
||||
#
|
||||
# def side_effect(*args, **kwargs):
|
||||
# rv = sess.get().json.return_value
|
||||
# sess.get().json.return_value = []
|
||||
# sess.get().json.side_effect = None
|
||||
# return rv
|
||||
#
|
||||
# resp = [{'name': 'is-name'}]
|
||||
# sess.get().json.return_value = resp
|
||||
# sess.get().json.side_effect = side_effect
|
||||
#
|
||||
# data = lib_container.list_containers(
|
||||
# self.app.client_manager.session,
|
||||
# fake_url,
|
||||
# full_listing=True,
|
||||
# )
|
||||
#
|
||||
# # Check expected values
|
||||
# sess.get.assert_called_with(
|
||||
# fake_url,
|
||||
# params={
|
||||
# 'format': 'json',
|
||||
# 'marker': 'is-name',
|
||||
# }
|
||||
# )
|
||||
# self.assertEqual(resp, data)
|
||||
|
||||
def test_container_show(self):
|
||||
headers = {
|
||||
'X-Container-Meta-Owner': FAKE_ACCOUNT,
|
||||
'x-container-object-count': '1',
|
||||
'x-container-bytes-used': '577',
|
||||
}
|
||||
resp = {
|
||||
'account': FAKE_ACCOUNT,
|
||||
'container': 'qaz',
|
||||
'object_count': '1',
|
||||
'bytes_used': '577',
|
||||
'read_acl': None,
|
||||
'write_acl': None,
|
||||
'sync_to': None,
|
||||
'sync_key': None,
|
||||
}
|
||||
self.requests_mock.register_uri(
|
||||
'HEAD',
|
||||
FAKE_URL + '/qaz',
|
||||
headers=headers,
|
||||
status_code=204,
|
||||
)
|
||||
ret = self.api.container_show(container='qaz')
|
||||
self.assertEqual(resp, ret)
|
||||
|
||||
|
||||
class TestObject(TestObjectAPIv1):
|
||||
|
||||
def setUp(self):
|
||||
super(TestObject, self).setUp()
|
||||
|
||||
def test_object_create(self):
|
||||
headers = {
|
||||
'etag': 'youreit',
|
||||
'x-trans-id': '1qaz2wsx',
|
||||
}
|
||||
self.requests_mock.register_uri(
|
||||
'PUT',
|
||||
FAKE_URL + '/qaz/requirements.txt',
|
||||
headers=headers,
|
||||
status_code=201,
|
||||
)
|
||||
ret = self.api.object_create(
|
||||
container='qaz',
|
||||
object='requirements.txt',
|
||||
)
|
||||
data = {
|
||||
'account': FAKE_ACCOUNT,
|
||||
'container': 'qaz',
|
||||
'object': 'requirements.txt',
|
||||
'etag': 'youreit',
|
||||
'x-trans-id': '1qaz2wsx',
|
||||
}
|
||||
self.assertEqual(data, ret)
|
||||
|
||||
def test_object_delete(self):
|
||||
self.requests_mock.register_uri(
|
||||
'DELETE',
|
||||
FAKE_URL + '/qaz/wsx',
|
||||
status_code=204,
|
||||
)
|
||||
ret = self.api.object_delete(
|
||||
container='qaz',
|
||||
object='wsx',
|
||||
)
|
||||
self.assertIsNone(ret)
|
||||
|
||||
def test_object_list_no_options(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/qaz',
|
||||
json=LIST_OBJECT_RESP,
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.object_list(container='qaz')
|
||||
self.assertEqual(LIST_OBJECT_RESP, ret)
|
||||
|
||||
def test_object_list_delimiter(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/qaz?delimiter=%7C',
|
||||
json=LIST_OBJECT_RESP,
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.object_list(
|
||||
container='qaz',
|
||||
delimiter='|',
|
||||
)
|
||||
self.assertEqual(LIST_OBJECT_RESP, ret)
|
||||
|
||||
def test_object_list_prefix(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/qaz?prefix=foo%2f',
|
||||
json=LIST_OBJECT_RESP,
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.object_list(
|
||||
container='qaz',
|
||||
prefix='foo/',
|
||||
)
|
||||
self.assertEqual(LIST_OBJECT_RESP, ret)
|
||||
|
||||
def test_object_list_marker_limit_end(self):
|
||||
self.requests_mock.register_uri(
|
||||
'GET',
|
||||
FAKE_URL + '/qaz?marker=next&limit=2&end_marker=stop',
|
||||
json=LIST_CONTAINER_RESP,
|
||||
status_code=200,
|
||||
)
|
||||
ret = self.api.object_list(
|
||||
container='qaz',
|
||||
marker='next',
|
||||
limit=2,
|
||||
end_marker='stop',
|
||||
)
|
||||
self.assertEqual(LIST_CONTAINER_RESP, ret)
|
||||
|
||||
# def test_list_objects_full_listing(self):
|
||||
# sess = self.app.client_manager.session
|
||||
#
|
||||
# def side_effect(*args, **kwargs):
|
||||
# rv = sess.get().json.return_value
|
||||
# sess.get().json.return_value = []
|
||||
# sess.get().json.side_effect = None
|
||||
# return rv
|
||||
#
|
||||
# resp = [{'name': 'is-name'}]
|
||||
# sess.get().json.return_value = resp
|
||||
# sess.get().json.side_effect = side_effect
|
||||
#
|
||||
# data = lib_object.list_objects(
|
||||
# sess,
|
||||
# fake_url,
|
||||
# fake_container,
|
||||
# full_listing=True,
|
||||
# )
|
||||
#
|
||||
# # Check expected values
|
||||
# sess.get.assert_called_with(
|
||||
# fake_url + '/' + fake_container,
|
||||
# params={
|
||||
# 'format': 'json',
|
||||
# 'marker': 'is-name',
|
||||
# }
|
||||
# )
|
||||
# self.assertEqual(resp, data)
|
||||
|
||||
def test_object_show(self):
|
||||
headers = {
|
||||
'content-type': 'text/alpha',
|
||||
'content-length': '577',
|
||||
'last-modified': '20130101',
|
||||
'etag': 'qaz',
|
||||
'x-container-meta-owner': FAKE_ACCOUNT,
|
||||
'x-object-meta-wife': 'Wilma',
|
||||
'x-tra-header': 'yabba-dabba-do',
|
||||
}
|
||||
resp = {
|
||||
'account': FAKE_ACCOUNT,
|
||||
'container': 'qaz',
|
||||
'object': FAKE_OBJECT,
|
||||
'content-type': 'text/alpha',
|
||||
'content-length': '577',
|
||||
'last-modified': '20130101',
|
||||
'etag': 'qaz',
|
||||
'wife': 'Wilma',
|
||||
'x-tra-header': 'yabba-dabba-do',
|
||||
}
|
||||
self.requests_mock.register_uri(
|
||||
'HEAD',
|
||||
FAKE_URL + '/qaz/' + FAKE_OBJECT,
|
||||
headers=headers,
|
||||
status_code=204,
|
||||
)
|
||||
ret = self.api.object_show(
|
||||
container='qaz',
|
||||
object=FAKE_OBJECT,
|
||||
)
|
||||
self.assertEqual(resp, ret)
|
@ -1,207 +0,0 @@
|
||||
# Copyright 2013 Nebula Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Test Object API library module"""
|
||||
|
||||
import mock
|
||||
|
||||
from openstackclient.object.v1.lib import container as lib_container
|
||||
from openstackclient.tests import fakes
|
||||
from openstackclient.tests.object.v1 import fakes as object_fakes
|
||||
|
||||
|
||||
fake_account = 'q12we34r'
|
||||
fake_auth = '11223344556677889900'
|
||||
fake_url = 'http://gopher.com/v1/' + fake_account
|
||||
|
||||
fake_container = 'rainbarrel'
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
def __init__(self, endpoint=None, **kwargs):
|
||||
self.endpoint = fake_url
|
||||
self.token = fake_auth
|
||||
|
||||
|
||||
class TestContainer(object_fakes.TestObjectv1):
|
||||
|
||||
def setUp(self):
|
||||
super(TestContainer, self).setUp()
|
||||
self.app.client_manager.session = mock.MagicMock()
|
||||
|
||||
|
||||
class TestContainerList(TestContainer):
|
||||
|
||||
def test_container_list_no_options(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url,
|
||||
params={
|
||||
'format': 'json',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_container_list_marker(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
marker='next',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url,
|
||||
params={
|
||||
'format': 'json',
|
||||
'marker': 'next',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_container_list_limit(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
limit=5,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url,
|
||||
params={
|
||||
'format': 'json',
|
||||
'limit': 5,
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_container_list_end_marker(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
end_marker='last',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url,
|
||||
params={
|
||||
'format': 'json',
|
||||
'end_marker': 'last',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_container_list_prefix(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
prefix='foo/',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url,
|
||||
params={
|
||||
'format': 'json',
|
||||
'prefix': 'foo/',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_container_list_full_listing(self):
|
||||
sess = self.app.client_manager.session
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
rv = sess.get().json.return_value
|
||||
sess.get().json.return_value = []
|
||||
sess.get().json.side_effect = None
|
||||
return rv
|
||||
|
||||
resp = [{'name': 'is-name'}]
|
||||
sess.get().json.return_value = resp
|
||||
sess.get().json.side_effect = side_effect
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
full_listing=True,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
sess.get.assert_called_with(
|
||||
fake_url,
|
||||
params={
|
||||
'format': 'json',
|
||||
'marker': 'is-name',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
|
||||
class TestContainerShow(TestContainer):
|
||||
|
||||
def test_container_show_no_options(self):
|
||||
resp = {
|
||||
'X-Container-Meta-Owner': fake_account,
|
||||
'x-container-object-count': 1,
|
||||
'x-container-bytes-used': 577,
|
||||
}
|
||||
self.app.client_manager.session.head.return_value = \
|
||||
fakes.FakeResponse(headers=resp)
|
||||
|
||||
data = lib_container.show_container(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
'is-name',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.head.assert_called_with(
|
||||
fake_url + '/is-name',
|
||||
)
|
||||
|
||||
data_expected = {
|
||||
'account': fake_account,
|
||||
'container': 'is-name',
|
||||
'object_count': 1,
|
||||
'bytes_used': 577,
|
||||
'read_acl': None,
|
||||
'write_acl': None,
|
||||
'sync_to': None,
|
||||
'sync_key': None,
|
||||
}
|
||||
self.assertEqual(data_expected, data)
|
@ -1,295 +0,0 @@
|
||||
# Copyright 2013 Nebula Inc.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Test Object API library module"""
|
||||
|
||||
import mock
|
||||
|
||||
from openstackclient.object.v1.lib import object as lib_object
|
||||
from openstackclient.tests import fakes
|
||||
from openstackclient.tests.object.v1 import fakes as object_fakes
|
||||
|
||||
|
||||
fake_account = 'q12we34r'
|
||||
fake_auth = '11223344556677889900'
|
||||
fake_url = 'http://gopher.com/v1/' + fake_account
|
||||
|
||||
fake_container = 'rainbarrel'
|
||||
fake_object = 'raindrop'
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
def __init__(self, endpoint=None, **kwargs):
|
||||
self.endpoint = fake_url
|
||||
self.token = fake_auth
|
||||
|
||||
|
||||
class TestObject(object_fakes.TestObjectv1):
|
||||
|
||||
def setUp(self):
|
||||
super(TestObject, self).setUp()
|
||||
self.app.client_manager.session = mock.MagicMock()
|
||||
|
||||
|
||||
class TestObjectListObjects(TestObject):
|
||||
|
||||
def test_list_objects_no_options(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url + '/' + fake_container,
|
||||
params={
|
||||
'format': 'json',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_list_objects_marker(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
marker='next',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url + '/' + fake_container,
|
||||
params={
|
||||
'format': 'json',
|
||||
'marker': 'next',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_list_objects_limit(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
limit=5,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url + '/' + fake_container,
|
||||
params={
|
||||
'format': 'json',
|
||||
'limit': 5,
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_list_objects_end_marker(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
end_marker='last',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url + '/' + fake_container,
|
||||
params={
|
||||
'format': 'json',
|
||||
'end_marker': 'last',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_list_objects_delimiter(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
delimiter='|',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
# NOTE(dtroyer): requests handles the URL encoding and we're
|
||||
# mocking that so use the otherwise-not-legal
|
||||
# pipe '|' char in the response.
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url + '/' + fake_container,
|
||||
params={
|
||||
'format': 'json',
|
||||
'delimiter': '|',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_list_objects_prefix(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
prefix='foo/',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url + '/' + fake_container,
|
||||
params={
|
||||
'format': 'json',
|
||||
'prefix': 'foo/',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_list_objects_path(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.client_manager.session.get().json.return_value = resp
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
path='next',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.get.assert_called_with(
|
||||
fake_url + '/' + fake_container,
|
||||
params={
|
||||
'format': 'json',
|
||||
'path': 'next',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
def test_list_objects_full_listing(self):
|
||||
sess = self.app.client_manager.session
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
rv = sess.get().json.return_value
|
||||
sess.get().json.return_value = []
|
||||
sess.get().json.side_effect = None
|
||||
return rv
|
||||
|
||||
resp = [{'name': 'is-name'}]
|
||||
sess.get().json.return_value = resp
|
||||
sess.get().json.side_effect = side_effect
|
||||
|
||||
data = lib_object.list_objects(
|
||||
sess,
|
||||
fake_url,
|
||||
fake_container,
|
||||
full_listing=True,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
sess.get.assert_called_with(
|
||||
fake_url + '/' + fake_container,
|
||||
params={
|
||||
'format': 'json',
|
||||
'marker': 'is-name',
|
||||
}
|
||||
)
|
||||
self.assertEqual(resp, data)
|
||||
|
||||
|
||||
class TestObjectShowObjects(TestObject):
|
||||
|
||||
def test_object_show_no_options(self):
|
||||
resp = {
|
||||
'content-type': 'text/alpha',
|
||||
'x-container-meta-owner': fake_account,
|
||||
}
|
||||
self.app.client_manager.session.head.return_value = \
|
||||
fakes.FakeResponse(headers=resp)
|
||||
|
||||
data = lib_object.show_object(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
fake_object,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.head.assert_called_with(
|
||||
fake_url + '/%s/%s' % (fake_container, fake_object),
|
||||
)
|
||||
|
||||
data_expected = {
|
||||
'account': fake_account,
|
||||
'container': fake_container,
|
||||
'object': fake_object,
|
||||
'content-type': 'text/alpha',
|
||||
}
|
||||
self.assertEqual(data_expected, data)
|
||||
|
||||
def test_object_show_all_options(self):
|
||||
resp = {
|
||||
'content-type': 'text/alpha',
|
||||
'content-length': 577,
|
||||
'last-modified': '20130101',
|
||||
'etag': 'qaz',
|
||||
'x-container-meta-owner': fake_account,
|
||||
'x-object-manifest': None,
|
||||
'x-object-meta-wife': 'Wilma',
|
||||
'x-tra-header': 'yabba-dabba-do',
|
||||
}
|
||||
self.app.client_manager.session.head.return_value = \
|
||||
fakes.FakeResponse(headers=resp)
|
||||
|
||||
data = lib_object.show_object(
|
||||
self.app.client_manager.session,
|
||||
fake_url,
|
||||
fake_container,
|
||||
fake_object,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.client_manager.session.head.assert_called_with(
|
||||
fake_url + '/%s/%s' % (fake_container, fake_object),
|
||||
)
|
||||
|
||||
data_expected = {
|
||||
'account': fake_account,
|
||||
'container': fake_container,
|
||||
'object': fake_object,
|
||||
'content-type': 'text/alpha',
|
||||
'content-length': 577,
|
||||
'last-modified': '20130101',
|
||||
'etag': 'qaz',
|
||||
'x-object-manifest': None,
|
||||
'wife': 'Wilma',
|
||||
'x-tra-header': 'yabba-dabba-do',
|
||||
}
|
||||
self.assertEqual(data_expected, data)
|
@ -16,6 +16,7 @@
|
||||
import copy
|
||||
import mock
|
||||
|
||||
from openstackclient.api import object_store_v1 as object_store
|
||||
from openstackclient.object.v1 import container
|
||||
from openstackclient.tests.object.v1 import fakes as object_fakes
|
||||
|
||||
@ -30,28 +31,20 @@ class FakeClient(object):
|
||||
self.token = AUTH_TOKEN
|
||||
|
||||
|
||||
class TestObject(object_fakes.TestObjectv1):
|
||||
class TestContainer(object_fakes.TestObjectv1):
|
||||
def setUp(self):
|
||||
super(TestObject, self).setUp()
|
||||
|
||||
|
||||
class TestObjectClient(TestObject):
|
||||
|
||||
def test_make_client(self):
|
||||
self.assertEqual(
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
AUTH_URL,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.client_manager.object_store.token,
|
||||
AUTH_TOKEN,
|
||||
super(TestContainer, self).setUp()
|
||||
self.app.client_manager.object_store = object_store.APIv1(
|
||||
session=mock.Mock(),
|
||||
service_type="object-store",
|
||||
)
|
||||
self.api = self.app.client_manager.object_store
|
||||
|
||||
|
||||
@mock.patch(
|
||||
'openstackclient.object.v1.container.lib_container.list_containers'
|
||||
'openstackclient.api.object_store_v1.APIv1.container_list'
|
||||
)
|
||||
class TestContainerList(TestObject):
|
||||
class TestContainerList(TestContainer):
|
||||
|
||||
def setUp(self):
|
||||
super(TestContainerList, self).setUp()
|
||||
@ -77,8 +70,6 @@ class TestContainerList(TestObject):
|
||||
kwargs = {
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -113,8 +104,6 @@ class TestContainerList(TestObject):
|
||||
'prefix': 'bit',
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -134,43 +123,10 @@ class TestContainerList(TestObject):
|
||||
|
||||
arglist = [
|
||||
'--marker', object_fakes.container_name,
|
||||
]
|
||||
verifylist = [
|
||||
('marker', object_fakes.container_name),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
|
||||
# DisplayCommandBase.take_action() returns two tuples
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'marker': object_fakes.container_name,
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.container_name, ),
|
||||
(object_fakes.container_name_3, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_containers_end_marker(self, c_mock):
|
||||
c_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.CONTAINER),
|
||||
copy.deepcopy(object_fakes.CONTAINER_3),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--end-marker', object_fakes.container_name_3,
|
||||
]
|
||||
verifylist = [
|
||||
('marker', object_fakes.container_name),
|
||||
('end_marker', object_fakes.container_name_3),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||
@ -180,11 +136,10 @@ class TestContainerList(TestObject):
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
'marker': object_fakes.container_name,
|
||||
'end_marker': object_fakes.container_name_3,
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -218,8 +173,6 @@ class TestContainerList(TestObject):
|
||||
'limit': 2,
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -252,8 +205,6 @@ class TestContainerList(TestObject):
|
||||
kwargs = {
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -296,8 +247,6 @@ class TestContainerList(TestObject):
|
||||
'full_listing': True,
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -312,9 +261,9 @@ class TestContainerList(TestObject):
|
||||
|
||||
|
||||
@mock.patch(
|
||||
'openstackclient.object.v1.container.lib_container.show_container'
|
||||
'openstackclient.api.object_store_v1.APIv1.container_show'
|
||||
)
|
||||
class TestContainerShow(TestObject):
|
||||
class TestContainerShow(TestContainer):
|
||||
|
||||
def setUp(self):
|
||||
super(TestContainerShow, self).setUp()
|
||||
@ -341,9 +290,7 @@ class TestContainerShow(TestObject):
|
||||
}
|
||||
# lib.container.show_container(api, url, container)
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name,
|
||||
container=object_fakes.container_name,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
@ -16,6 +16,7 @@ import copy
|
||||
from requests_mock.contrib import fixture
|
||||
|
||||
from keystoneclient import session
|
||||
from openstackclient.api import object_store_v1 as object_store
|
||||
from openstackclient.object.v1 import container
|
||||
from openstackclient.tests.object.v1 import fakes as object_fakes
|
||||
|
||||
@ -29,7 +30,10 @@ class TestObjectAll(object_fakes.TestObjectv1):
|
||||
self.requests_mock = self.useFixture(fixture.Fixture())
|
||||
|
||||
# TODO(dtroyer): move this to object_fakes.TestObjectv1
|
||||
self.app.client_manager.object_store.endpoint = object_fakes.ENDPOINT
|
||||
self.app.client_manager.object_store = object_store.APIv1(
|
||||
session=self.app.client_manager.session,
|
||||
endpoint=object_fakes.ENDPOINT,
|
||||
)
|
||||
|
||||
|
||||
class TestContainerCreate(TestObjectAll):
|
||||
|
@ -16,6 +16,7 @@
|
||||
import copy
|
||||
import mock
|
||||
|
||||
from openstackclient.api import object_store_v1 as object_store
|
||||
from openstackclient.object.v1 import object as obj
|
||||
from openstackclient.tests.object.v1 import fakes as object_fakes
|
||||
|
||||
@ -27,23 +28,15 @@ AUTH_URL = "http://0.0.0.0"
|
||||
class TestObject(object_fakes.TestObjectv1):
|
||||
def setUp(self):
|
||||
super(TestObject, self).setUp()
|
||||
|
||||
|
||||
class TestObjectClient(TestObject):
|
||||
|
||||
def test_make_client(self):
|
||||
self.assertEqual(
|
||||
self.app.client_manager.object_store.endpoint,
|
||||
AUTH_URL,
|
||||
)
|
||||
self.assertEqual(
|
||||
self.app.client_manager.object_store.token,
|
||||
AUTH_TOKEN,
|
||||
self.app.client_manager.object_store = object_store.APIv1(
|
||||
session=mock.Mock(),
|
||||
service_type="object-store",
|
||||
)
|
||||
self.api = self.app.client_manager.object_store
|
||||
|
||||
|
||||
@mock.patch(
|
||||
'openstackclient.object.v1.object.lib_object.list_objects'
|
||||
'openstackclient.api.object_store_v1.APIv1.object_list'
|
||||
)
|
||||
class TestObjectList(TestObject):
|
||||
|
||||
@ -71,9 +64,7 @@ class TestObjectList(TestObject):
|
||||
columns, data = self.cmd.take_action(parsed_args)
|
||||
|
||||
o_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name,
|
||||
container=object_fakes.container_name,
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
@ -107,9 +98,7 @@ class TestObjectList(TestObject):
|
||||
'prefix': 'floppy',
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
container=object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -143,9 +132,7 @@ class TestObjectList(TestObject):
|
||||
'delimiter': '=',
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
container=object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -179,9 +166,7 @@ class TestObjectList(TestObject):
|
||||
'marker': object_fakes.object_name_2,
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
container=object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -215,9 +200,7 @@ class TestObjectList(TestObject):
|
||||
'end_marker': object_fakes.object_name_2,
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
container=object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -251,9 +234,7 @@ class TestObjectList(TestObject):
|
||||
'limit': 2,
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
container=object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -287,9 +268,7 @@ class TestObjectList(TestObject):
|
||||
kwargs = {
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name,
|
||||
container=object_fakes.container_name,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -337,9 +316,7 @@ class TestObjectList(TestObject):
|
||||
'full_listing': True,
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name,
|
||||
container=object_fakes.container_name,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
@ -353,7 +330,7 @@ class TestObjectList(TestObject):
|
||||
|
||||
|
||||
@mock.patch(
|
||||
'openstackclient.object.v1.object.lib_object.show_object'
|
||||
'openstackclient.api.object_store_v1.APIv1.object_show'
|
||||
)
|
||||
class TestObjectShow(TestObject):
|
||||
|
||||
@ -384,10 +361,8 @@ class TestObjectShow(TestObject):
|
||||
}
|
||||
# lib.container.show_container(api, url, container)
|
||||
c_mock.assert_called_with(
|
||||
self.app.client_manager.session,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name,
|
||||
object_fakes.object_name_1,
|
||||
container=object_fakes.container_name,
|
||||
object=object_fakes.object_name_1,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user