Object API commands using our REST API layer
* Add object-store API to ClientManager * Add object-store client * Add Object API library in openstackclient.object.v1.lib * Add Object API {container,object} list commands * Add library tests * Add command tests This should complete the Object v1 container and object list commands Change-Id: Ib1770d45efa8871959826b85faafa1e0bcef0a03
This commit is contained in:
parent
17f13f7bf4
commit
725e2543ef
@ -20,6 +20,7 @@ import logging
|
||||
from openstackclient.compute import client as compute_client
|
||||
from openstackclient.identity import client as identity_client
|
||||
from openstackclient.image import client as image_client
|
||||
from openstackclient.object import client as object_client
|
||||
from openstackclient.volume import client as volume_client
|
||||
|
||||
|
||||
@ -44,6 +45,7 @@ class ClientManager(object):
|
||||
compute = ClientCache(compute_client.make_client)
|
||||
identity = ClientCache(identity_client.make_client)
|
||||
image = ClientCache(image_client.make_client)
|
||||
object = ClientCache(object_client.make_client)
|
||||
volume = ClientCache(volume_client.make_client)
|
||||
|
||||
def __init__(self, token=None, url=None, auth_url=None, project_name=None,
|
||||
|
12
openstackclient/object/__init__.py
Normal file
12
openstackclient/object/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
# 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.
|
||||
#
|
58
openstackclient/object/client.py
Normal file
58
openstackclient/object/client.py
Normal file
@ -0,0 +1,58 @@
|
||||
# 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 client"""
|
||||
|
||||
import logging
|
||||
|
||||
from openstackclient.common import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
API_NAME = 'object-store'
|
||||
API_VERSIONS = {
|
||||
'1': 'openstackclient.object.client.ObjectClientv1',
|
||||
}
|
||||
|
||||
|
||||
def make_client(instance):
|
||||
"""Returns an object service client."""
|
||||
object_client = utils.get_client_class(
|
||||
API_NAME,
|
||||
instance._api_version[API_NAME],
|
||||
API_VERSIONS)
|
||||
if instance._url:
|
||||
endpoint = instance._url
|
||||
else:
|
||||
endpoint = instance.get_endpoint_for_service_type(API_NAME)
|
||||
LOG.debug('instantiating object client')
|
||||
client = object_client(
|
||||
endpoint=endpoint,
|
||||
token=instance._token,
|
||||
)
|
||||
return client
|
||||
|
||||
|
||||
class ObjectClientv1(object):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
endpoint_type='publicURL',
|
||||
endpoint=None,
|
||||
token=None,
|
||||
):
|
||||
self.endpoint_type = endpoint_type
|
||||
self.endpoint = endpoint
|
||||
self.token = token
|
12
openstackclient/object/v1/__init__.py
Normal file
12
openstackclient/object/v1/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
# 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.
|
||||
#
|
100
openstackclient/object/v1/container.py
Normal file
100
openstackclient/object/v1/container.py
Normal file
@ -0,0 +1,100 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Container v1 action implementations"""
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from cliff import lister
|
||||
|
||||
from openstackclient.common import utils
|
||||
from openstackclient.object.v1.lib import container as lib_container
|
||||
|
||||
|
||||
class ListContainer(lister.Lister):
|
||||
"""List containers"""
|
||||
|
||||
log = logging.getLogger(__name__ + '.ListContainer')
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListContainer, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
"--prefix",
|
||||
metavar="<prefix>",
|
||||
help="Filter list using <prefix>",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--marker",
|
||||
metavar="<marker>",
|
||||
help="Anchor for paging",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--end-marker",
|
||||
metavar="<end-marker>",
|
||||
help="End anchor for paging",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--limit",
|
||||
metavar="<limit>",
|
||||
type=int,
|
||||
help="Limit the number of containers returned",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--long',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='List additional fields in output',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--all',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='List all containers (default is 10000)',
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug('take_action(%s)' % parsed_args)
|
||||
|
||||
if parsed_args.long:
|
||||
columns = ('Name', 'Bytes', 'Count')
|
||||
else:
|
||||
columns = ('Name',)
|
||||
|
||||
kwargs = {}
|
||||
if parsed_args.prefix:
|
||||
kwargs['prefix'] = parsed_args.prefix
|
||||
if parsed_args.marker:
|
||||
kwargs['marker'] = parsed_args.marker
|
||||
if parsed_args.end_marker:
|
||||
kwargs['end_marker'] = parsed_args.end_marker
|
||||
if parsed_args.limit:
|
||||
kwargs['limit'] = parsed_args.limit
|
||||
if parsed_args.all:
|
||||
kwargs['full_listing'] = True
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
**kwargs
|
||||
)
|
||||
#print "data: %s" % data
|
||||
|
||||
return (columns,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
formatters={},
|
||||
) for s in data))
|
12
openstackclient/object/v1/lib/__init__.py
Normal file
12
openstackclient/object/v1/lib/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
# 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.
|
||||
#
|
77
openstackclient/object/v1/lib/container.py
Normal file
77
openstackclient/object/v1/lib/container.py
Normal file
@ -0,0 +1,77 @@
|
||||
# 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"""
|
||||
|
||||
|
||||
def list_containers(
|
||||
api,
|
||||
url,
|
||||
marker=None,
|
||||
limit=None,
|
||||
end_marker=None,
|
||||
prefix=None,
|
||||
full_listing=False,
|
||||
):
|
||||
"""Get containers in an account
|
||||
|
||||
:param api: a restapi 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(
|
||||
api,
|
||||
url,
|
||||
marker,
|
||||
limit,
|
||||
end_marker,
|
||||
prefix,
|
||||
)
|
||||
while listing:
|
||||
marker = listing[-1]['name']
|
||||
listing = list_containers(
|
||||
api,
|
||||
url,
|
||||
marker,
|
||||
limit,
|
||||
end_marker,
|
||||
prefix,
|
||||
)
|
||||
if listing:
|
||||
data.extend(listing)
|
||||
return data
|
||||
|
||||
object_url = url
|
||||
query = "format=json"
|
||||
if marker:
|
||||
query += '&marker=%s' % marker
|
||||
if limit:
|
||||
query += '&limit=%d' % limit
|
||||
if end_marker:
|
||||
query += '&end_marker=%s' % end_marker
|
||||
if prefix:
|
||||
query += '&prefix=%s' % prefix
|
||||
url = "%s?%s" % (object_url, query)
|
||||
response = api.request('GET', url)
|
||||
return response.json()
|
97
openstackclient/object/v1/lib/object.py
Normal file
97
openstackclient/object/v1/lib/object.py
Normal file
@ -0,0 +1,97 @@
|
||||
# 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"""
|
||||
|
||||
|
||||
def list_objects(
|
||||
api,
|
||||
url,
|
||||
container,
|
||||
marker=None,
|
||||
limit=None,
|
||||
end_marker=None,
|
||||
delimiter=None,
|
||||
prefix=None,
|
||||
path=None,
|
||||
full_listing=False,
|
||||
):
|
||||
"""Get objects in a container
|
||||
|
||||
:param api: a restapi 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(
|
||||
api,
|
||||
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(
|
||||
api,
|
||||
url,
|
||||
container,
|
||||
marker,
|
||||
limit,
|
||||
end_marker,
|
||||
delimiter,
|
||||
prefix,
|
||||
path,
|
||||
)
|
||||
if listing:
|
||||
data.extend(listing)
|
||||
return data
|
||||
|
||||
object_url = url
|
||||
query = "format=json"
|
||||
if marker:
|
||||
query += '&marker=%s' % marker
|
||||
if limit:
|
||||
query += '&limit=%d' % limit
|
||||
if end_marker:
|
||||
query += '&end_marker=%s' % end_marker
|
||||
if delimiter:
|
||||
query += '&delimiter=%s' % delimiter
|
||||
if prefix:
|
||||
query += '&prefix=%s' % prefix
|
||||
if path:
|
||||
query += '&path=%s' % path
|
||||
url = "%s/%s?%s" % (object_url, container, query)
|
||||
response = api.request('GET', url)
|
||||
return response.json()
|
118
openstackclient/object/v1/object.py
Normal file
118
openstackclient/object/v1/object.py
Normal file
@ -0,0 +1,118 @@
|
||||
# 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 action implementations"""
|
||||
|
||||
|
||||
import logging
|
||||
|
||||
from cliff import lister
|
||||
|
||||
from openstackclient.common import utils
|
||||
from openstackclient.object.v1.lib import object as lib_object
|
||||
|
||||
|
||||
class ListObject(lister.Lister):
|
||||
"""List objects"""
|
||||
|
||||
log = logging.getLogger(__name__ + '.ListObject')
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(ListObject, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
"container",
|
||||
metavar="<container-name>",
|
||||
help="List contents of container-name",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--prefix",
|
||||
metavar="<prefix>",
|
||||
help="Filter list using <prefix>",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--delimiter",
|
||||
metavar="<delimiter>",
|
||||
help="Roll up items with <delimiter>",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--marker",
|
||||
metavar="<marker>",
|
||||
help="Anchor for paging",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--end-marker",
|
||||
metavar="<end-marker>",
|
||||
help="End anchor for paging",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--limit",
|
||||
metavar="<limit>",
|
||||
type=int,
|
||||
help="Limit the number of objects returned",
|
||||
)
|
||||
parser.add_argument(
|
||||
'--long',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='List additional fields in output',
|
||||
)
|
||||
parser.add_argument(
|
||||
'--all',
|
||||
action='store_true',
|
||||
default=False,
|
||||
help='List all objects in container (default is 10000)',
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
self.log.debug('take_action(%s)' % parsed_args)
|
||||
|
||||
if parsed_args.long:
|
||||
columns = (
|
||||
'Name',
|
||||
'Bytes',
|
||||
'Hash',
|
||||
'Content Type',
|
||||
'Last Modified',
|
||||
)
|
||||
else:
|
||||
columns = ('Name',)
|
||||
|
||||
kwargs = {}
|
||||
if parsed_args.prefix:
|
||||
kwargs['prefix'] = parsed_args.prefix
|
||||
if parsed_args.delimiter:
|
||||
kwargs['delimiter'] = parsed_args.delimiter
|
||||
if parsed_args.marker:
|
||||
kwargs['marker'] = parsed_args.marker
|
||||
if parsed_args.end_marker:
|
||||
kwargs['end_marker'] = parsed_args.end_marker
|
||||
if parsed_args.limit:
|
||||
kwargs['limit'] = parsed_args.limit
|
||||
if parsed_args.all:
|
||||
kwargs['full_listing'] = True
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
parsed_args.container,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
return (columns,
|
||||
(utils.get_dict_properties(
|
||||
s, columns,
|
||||
formatters={},
|
||||
) for s in data))
|
@ -38,6 +38,7 @@ KEYRING_SERVICE = 'openstack'
|
||||
DEFAULT_COMPUTE_API_VERSION = '2'
|
||||
DEFAULT_IDENTITY_API_VERSION = '2.0'
|
||||
DEFAULT_IMAGE_API_VERSION = '1'
|
||||
DEFAULT_OBJECT_API_VERSION = '1'
|
||||
DEFAULT_VOLUME_API_VERSION = '1'
|
||||
DEFAULT_DOMAIN = 'default'
|
||||
|
||||
@ -187,6 +188,15 @@ class OpenStackShell(app.App):
|
||||
help='Image API version, default=' +
|
||||
DEFAULT_IMAGE_API_VERSION +
|
||||
' (Env: OS_IMAGE_API_VERSION)')
|
||||
parser.add_argument(
|
||||
'--os-object-api-version',
|
||||
metavar='<object-api-version>',
|
||||
default=env(
|
||||
'OS_OBJECT_API_VERSION',
|
||||
default=DEFAULT_OBJECT_API_VERSION),
|
||||
help='Object API version, default=' +
|
||||
DEFAULT_OBJECT_API_VERSION +
|
||||
' (Env: OS_OBJECT_API_VERSION)')
|
||||
parser.add_argument(
|
||||
'--os-volume-api-version',
|
||||
metavar='<volume-api-version>',
|
||||
@ -339,14 +349,15 @@ class OpenStackShell(app.App):
|
||||
'compute': self.options.os_compute_api_version,
|
||||
'identity': self.options.os_identity_api_version,
|
||||
'image': self.options.os_image_api_version,
|
||||
'object-store': self.options.os_object_api_version,
|
||||
'volume': self.options.os_volume_api_version,
|
||||
}
|
||||
|
||||
# Add the API version-specific commands
|
||||
for api in self.api_version.keys():
|
||||
version = '.v' + self.api_version[api].replace('.', '_')
|
||||
self.command_manager.add_command_group(
|
||||
'openstack.' + api + version)
|
||||
cmd_group = 'openstack.' + api.replace('-', '_') + version
|
||||
self.command_manager.add_command_group(cmd_group)
|
||||
|
||||
# Commands that span multiple APIs
|
||||
self.command_manager.add_command_group(
|
||||
|
@ -44,6 +44,11 @@ class FakeClientManager(object):
|
||||
pass
|
||||
|
||||
|
||||
class FakeRESTApi(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
class FakeResource(object):
|
||||
def __init__(self, manager, info, loaded=False):
|
||||
self.manager = manager
|
||||
|
12
openstackclient/tests/object/__init__.py
Normal file
12
openstackclient/tests/object/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
# 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.
|
||||
#
|
67
openstackclient/tests/object/fakes.py
Normal file
67
openstackclient/tests/object/fakes.py
Normal file
@ -0,0 +1,67 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
container_name = 'bit-bucket'
|
||||
container_bytes = 1024
|
||||
container_count = 1
|
||||
|
||||
container_name_2 = 'archive'
|
||||
container_name_3 = 'bit-blit'
|
||||
|
||||
CONTAINER = {
|
||||
'name': container_name,
|
||||
'bytes': container_bytes,
|
||||
'count': container_count,
|
||||
}
|
||||
|
||||
CONTAINER_2 = {
|
||||
'name': container_name_2,
|
||||
'bytes': container_bytes * 2,
|
||||
'count': container_count * 2,
|
||||
}
|
||||
|
||||
CONTAINER_3 = {
|
||||
'name': container_name_3,
|
||||
'bytes': container_bytes * 3,
|
||||
'count': container_count * 3,
|
||||
}
|
||||
|
||||
object_name_1 = 'punch-card'
|
||||
object_bytes_1 = 80
|
||||
object_hash_1 = '1234567890'
|
||||
object_content_type_1 = 'text'
|
||||
object_modified_1 = 'today'
|
||||
|
||||
object_name_2 = 'floppy-disk'
|
||||
object_bytes_2 = 1440000
|
||||
object_hash_2 = '0987654321'
|
||||
object_content_type_2 = 'text'
|
||||
object_modified_2 = 'today'
|
||||
|
||||
OBJECT = {
|
||||
'name': object_name_1,
|
||||
'bytes': object_bytes_1,
|
||||
'hash': object_hash_1,
|
||||
'content_type': object_content_type_1,
|
||||
'last_modified': object_modified_1,
|
||||
}
|
||||
|
||||
OBJECT_2 = {
|
||||
'name': object_name_2,
|
||||
'bytes': object_bytes_2,
|
||||
'hash': object_hash_2,
|
||||
'content_type': object_content_type_2,
|
||||
'last_modified': object_modified_2,
|
||||
}
|
315
openstackclient/tests/object/test_container.py
Normal file
315
openstackclient/tests/object/test_container.py
Normal file
@ -0,0 +1,315 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import copy
|
||||
import mock
|
||||
|
||||
from openstackclient.common import clientmanager
|
||||
from openstackclient.object.v1 import container
|
||||
from openstackclient.tests.object import fakes as object_fakes
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
AUTH_TOKEN = "foobar"
|
||||
AUTH_URL = "http://0.0.0.0"
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
def __init__(self, endpoint=None, **kwargs):
|
||||
self.endpoint = AUTH_URL
|
||||
self.token = AUTH_TOKEN
|
||||
|
||||
|
||||
class TestObject(utils.TestCommand):
|
||||
def setUp(self):
|
||||
super(TestObject, self).setUp()
|
||||
|
||||
api_version = {"object-store": "1"}
|
||||
self.app.client_manager = clientmanager.ClientManager(
|
||||
token=AUTH_TOKEN,
|
||||
url=AUTH_URL,
|
||||
auth_url=AUTH_URL,
|
||||
api_version=api_version,
|
||||
)
|
||||
|
||||
|
||||
class TestObjectClient(TestObject):
|
||||
|
||||
def test_make_client(self):
|
||||
self.assertEqual(self.app.client_manager.object.endpoint, AUTH_URL)
|
||||
self.assertEqual(self.app.client_manager.object.token, AUTH_TOKEN)
|
||||
|
||||
|
||||
@mock.patch(
|
||||
'openstackclient.object.v1.container.lib_container.list_containers'
|
||||
)
|
||||
class TestContainerList(TestObject):
|
||||
|
||||
def setUp(self):
|
||||
super(TestContainerList, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = container.ListContainer(self.app, None)
|
||||
|
||||
def test_object_list_containers_no_options(self, c_mock):
|
||||
c_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.CONTAINER),
|
||||
copy.deepcopy(object_fakes.CONTAINER_3),
|
||||
copy.deepcopy(object_fakes.CONTAINER_2),
|
||||
]
|
||||
|
||||
arglist = []
|
||||
verifylist = []
|
||||
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 = {
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.container_name, ),
|
||||
(object_fakes.container_name_3, ),
|
||||
(object_fakes.container_name_2, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_containers_prefix(self, c_mock):
|
||||
c_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.CONTAINER),
|
||||
copy.deepcopy(object_fakes.CONTAINER_3),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--prefix', 'bit',
|
||||
]
|
||||
verifylist = [
|
||||
('prefix', 'bit'),
|
||||
]
|
||||
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 = {
|
||||
'prefix': 'bit',
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
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_marker(self, c_mock):
|
||||
c_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.CONTAINER),
|
||||
copy.deepcopy(object_fakes.CONTAINER_3),
|
||||
]
|
||||
|
||||
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.restapi,
|
||||
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 = [
|
||||
('end_marker', object_fakes.container_name_3),
|
||||
]
|
||||
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 = {
|
||||
'end_marker': object_fakes.container_name_3,
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
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_limit(self, c_mock):
|
||||
c_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.CONTAINER),
|
||||
copy.deepcopy(object_fakes.CONTAINER_3),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--limit', '2',
|
||||
]
|
||||
verifylist = [
|
||||
('limit', 2),
|
||||
]
|
||||
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 = {
|
||||
'limit': 2,
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
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_long(self, c_mock):
|
||||
c_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.CONTAINER),
|
||||
copy.deepcopy(object_fakes.CONTAINER_3),
|
||||
]
|
||||
|
||||
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)
|
||||
|
||||
# Set expected values
|
||||
kwargs = {
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name', 'Bytes', 'Count')
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(
|
||||
object_fakes.container_name,
|
||||
object_fakes.container_bytes,
|
||||
object_fakes.container_count,
|
||||
),
|
||||
(
|
||||
object_fakes.container_name_3,
|
||||
object_fakes.container_bytes * 3,
|
||||
object_fakes.container_count * 3,
|
||||
),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_containers_all(self, c_mock):
|
||||
c_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.CONTAINER),
|
||||
copy.deepcopy(object_fakes.CONTAINER_2),
|
||||
copy.deepcopy(object_fakes.CONTAINER_3),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--all',
|
||||
]
|
||||
verifylist = [
|
||||
('all', True),
|
||||
]
|
||||
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 = {
|
||||
'full_listing': True,
|
||||
}
|
||||
c_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.container_name, ),
|
||||
(object_fakes.container_name_2, ),
|
||||
(object_fakes.container_name_3, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
362
openstackclient/tests/object/test_object.py
Normal file
362
openstackclient/tests/object/test_object.py
Normal file
@ -0,0 +1,362 @@
|
||||
# Copyright 2013 OpenStack Foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
import copy
|
||||
import mock
|
||||
|
||||
from openstackclient.common import clientmanager
|
||||
from openstackclient.object.v1 import object as obj
|
||||
from openstackclient.tests.object import fakes as object_fakes
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
AUTH_TOKEN = "foobar"
|
||||
AUTH_URL = "http://0.0.0.0"
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
def __init__(self, endpoint=None, **kwargs):
|
||||
self.endpoint = AUTH_URL
|
||||
self.token = AUTH_TOKEN
|
||||
|
||||
|
||||
class TestObject(utils.TestCommand):
|
||||
def setUp(self):
|
||||
super(TestObject, self).setUp()
|
||||
|
||||
api_version = {"object-store": "1"}
|
||||
self.app.client_manager = clientmanager.ClientManager(
|
||||
token=AUTH_TOKEN,
|
||||
url=AUTH_URL,
|
||||
auth_url=AUTH_URL,
|
||||
api_version=api_version,
|
||||
)
|
||||
|
||||
|
||||
class TestObjectClient(TestObject):
|
||||
|
||||
def test_make_client(self):
|
||||
self.assertEqual(self.app.client_manager.object.endpoint, AUTH_URL)
|
||||
self.assertEqual(self.app.client_manager.object.token, AUTH_TOKEN)
|
||||
|
||||
|
||||
@mock.patch(
|
||||
'openstackclient.object.v1.object.lib_object.list_objects'
|
||||
)
|
||||
class TestObjectList(TestObject):
|
||||
|
||||
def setUp(self):
|
||||
super(TestObjectList, self).setUp()
|
||||
|
||||
# Get the command object to test
|
||||
self.cmd = obj.ListObject(self.app, None)
|
||||
|
||||
def test_object_list_objects_no_options(self, o_mock):
|
||||
o_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.OBJECT),
|
||||
copy.deepcopy(object_fakes.OBJECT_2),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
object_fakes.container_name,
|
||||
]
|
||||
verifylist = [
|
||||
('container', 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)
|
||||
|
||||
o_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name,
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.object_name_1, ),
|
||||
(object_fakes.object_name_2, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_objects_prefix(self, o_mock):
|
||||
o_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.OBJECT_2),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--prefix', 'floppy',
|
||||
object_fakes.container_name_2,
|
||||
]
|
||||
verifylist = [
|
||||
('prefix', 'floppy'),
|
||||
('container', object_fakes.container_name_2),
|
||||
]
|
||||
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 = {
|
||||
'prefix': 'floppy',
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.object_name_2, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_objects_delimiter(self, o_mock):
|
||||
o_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.OBJECT_2),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--delimiter', '=',
|
||||
object_fakes.container_name_2,
|
||||
]
|
||||
verifylist = [
|
||||
('delimiter', '='),
|
||||
('container', object_fakes.container_name_2),
|
||||
]
|
||||
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 = {
|
||||
'delimiter': '=',
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.object_name_2, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_objects_marker(self, o_mock):
|
||||
o_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.OBJECT_2),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--marker', object_fakes.object_name_2,
|
||||
object_fakes.container_name_2,
|
||||
]
|
||||
verifylist = [
|
||||
('marker', object_fakes.object_name_2),
|
||||
('container', object_fakes.container_name_2),
|
||||
]
|
||||
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.object_name_2,
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.object_name_2, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_objects_end_marker(self, o_mock):
|
||||
o_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.OBJECT_2),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--end-marker', object_fakes.object_name_2,
|
||||
object_fakes.container_name_2,
|
||||
]
|
||||
verifylist = [
|
||||
('end_marker', object_fakes.object_name_2),
|
||||
('container', object_fakes.container_name_2),
|
||||
]
|
||||
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 = {
|
||||
'end_marker': object_fakes.object_name_2,
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.object_name_2, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_objects_limit(self, o_mock):
|
||||
o_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.OBJECT_2),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--limit', '2',
|
||||
object_fakes.container_name_2,
|
||||
]
|
||||
verifylist = [
|
||||
('limit', 2),
|
||||
('container', object_fakes.container_name_2),
|
||||
]
|
||||
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 = {
|
||||
'limit': 2,
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name_2,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.object_name_2, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_objects_long(self, o_mock):
|
||||
o_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.OBJECT),
|
||||
copy.deepcopy(object_fakes.OBJECT_2),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--long',
|
||||
object_fakes.container_name,
|
||||
]
|
||||
verifylist = [
|
||||
('long', True),
|
||||
('container', 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 = {
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name', 'Bytes', 'Hash', 'Content Type', 'Last Modified')
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(
|
||||
object_fakes.object_name_1,
|
||||
object_fakes.object_bytes_1,
|
||||
object_fakes.object_hash_1,
|
||||
object_fakes.object_content_type_1,
|
||||
object_fakes.object_modified_1,
|
||||
),
|
||||
(
|
||||
object_fakes.object_name_2,
|
||||
object_fakes.object_bytes_2,
|
||||
object_fakes.object_hash_2,
|
||||
object_fakes.object_content_type_2,
|
||||
object_fakes.object_modified_2,
|
||||
),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
||||
|
||||
def test_object_list_objects_all(self, o_mock):
|
||||
o_mock.return_value = [
|
||||
copy.deepcopy(object_fakes.OBJECT),
|
||||
copy.deepcopy(object_fakes.OBJECT_2),
|
||||
]
|
||||
|
||||
arglist = [
|
||||
'--all',
|
||||
object_fakes.container_name,
|
||||
]
|
||||
verifylist = [
|
||||
('all', True),
|
||||
('container', 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 = {
|
||||
'full_listing': True,
|
||||
}
|
||||
o_mock.assert_called_with(
|
||||
self.app.restapi,
|
||||
AUTH_URL,
|
||||
object_fakes.container_name,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
collist = ('Name',)
|
||||
self.assertEqual(columns, collist)
|
||||
datalist = (
|
||||
(object_fakes.object_name_1, ),
|
||||
(object_fakes.object_name_2, ),
|
||||
)
|
||||
self.assertEqual(tuple(data), datalist)
|
12
openstackclient/tests/object/v1/__init__.py
Normal file
12
openstackclient/tests/object/v1/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
# 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.
|
||||
#
|
12
openstackclient/tests/object/v1/lib/__init__.py
Normal file
12
openstackclient/tests/object/v1/lib/__init__.py
Normal file
@ -0,0 +1,12 @@
|
||||
# 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.
|
||||
#
|
159
openstackclient/tests/object/v1/lib/test_container.py
Normal file
159
openstackclient/tests/object/v1/lib/test_container.py
Normal file
@ -0,0 +1,159 @@
|
||||
# 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"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import mock
|
||||
|
||||
|
||||
from openstackclient.object.v1.lib import container as lib_container
|
||||
from openstackclient.tests.common import test_restapi as restapi
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
fake_auth = '11223344556677889900'
|
||||
fake_url = 'http://gopher.com'
|
||||
|
||||
fake_container = 'rainbarrel'
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
def __init__(self, endpoint=None, **kwargs):
|
||||
self.endpoint = fake_url
|
||||
self.token = fake_auth
|
||||
|
||||
|
||||
class TestObject(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestObject, self).setUp()
|
||||
self.app.client_manager.object = FakeClient()
|
||||
self.app.restapi = mock.MagicMock()
|
||||
|
||||
|
||||
class TestObjectListContainers(TestObject):
|
||||
|
||||
def test_list_containers_no_options(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '?format=json',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_containers_marker(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
marker='next',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '?format=json&marker=next',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_containers_limit(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
limit=5,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '?format=json&limit=5',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_containers_end_marker(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
end_marker='last',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '?format=json&end_marker=last',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_containers_prefix(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
prefix='foo/',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '?format=json&prefix=foo/',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_containers_full_listing(self):
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
rv = self.app.restapi.request.return_value
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(
|
||||
data=[],
|
||||
)
|
||||
self.app.restapi.request.side_effect = None
|
||||
return rv
|
||||
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
self.app.restapi.request.side_effect = side_effect
|
||||
|
||||
data = lib_container.list_containers(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
full_listing=True,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '?format=json&marker=is-name',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
203
openstackclient/tests/object/v1/lib/test_object.py
Normal file
203
openstackclient/tests/object/v1/lib/test_object.py
Normal file
@ -0,0 +1,203 @@
|
||||
# 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"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import mock
|
||||
|
||||
from openstackclient.object.v1.lib import object as lib_object
|
||||
from openstackclient.tests.common import test_restapi as restapi
|
||||
from openstackclient.tests import utils
|
||||
|
||||
|
||||
fake_auth = '11223344556677889900'
|
||||
fake_url = 'http://gopher.com'
|
||||
|
||||
fake_container = 'rainbarrel'
|
||||
|
||||
|
||||
class FakeClient(object):
|
||||
def __init__(self, endpoint=None, **kwargs):
|
||||
self.endpoint = fake_url
|
||||
self.token = fake_auth
|
||||
|
||||
|
||||
class TestObject(utils.TestCommand):
|
||||
|
||||
def setUp(self):
|
||||
super(TestObject, self).setUp()
|
||||
self.app.client_manager.object = FakeClient()
|
||||
self.app.restapi = mock.MagicMock()
|
||||
|
||||
|
||||
class TestObjectListObjects(TestObject):
|
||||
|
||||
def test_list_objects_no_options(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
fake_container,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '/' + fake_container + '?format=json',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_objects_marker(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
fake_container,
|
||||
marker='next',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '/' + fake_container + '?format=json&marker=next',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_objects_limit(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
fake_container,
|
||||
limit=5,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '/' + fake_container + '?format=json&limit=5',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_objects_end_marker(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
fake_container,
|
||||
end_marker='last',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '/' + fake_container + '?format=json&end_marker=last',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_objects_delimiter(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
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.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '/' + fake_container + '?format=json&delimiter=|',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_objects_prefix(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
fake_container,
|
||||
prefix='foo/',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '/' + fake_container + '?format=json&prefix=foo/',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_objects_path(self):
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
fake_container,
|
||||
path='next',
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '/' + fake_container + '?format=json&path=next',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
||||
|
||||
def test_list_objects_full_listing(self):
|
||||
|
||||
def side_effect(*args, **kwargs):
|
||||
rv = self.app.restapi.request.return_value
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(
|
||||
data=[],
|
||||
)
|
||||
self.app.restapi.request.side_effect = None
|
||||
return rv
|
||||
|
||||
resp = [{'name': 'is-name'}]
|
||||
self.app.restapi.request.return_value = restapi.FakeResponse(data=resp)
|
||||
self.app.restapi.request.side_effect = side_effect
|
||||
|
||||
data = lib_object.list_objects(
|
||||
self.app.restapi,
|
||||
self.app.client_manager.object.endpoint,
|
||||
fake_container,
|
||||
full_listing=True,
|
||||
)
|
||||
|
||||
# Check expected values
|
||||
self.app.restapi.request.assert_called_with(
|
||||
'GET',
|
||||
fake_url + '/' + fake_container + '?format=json&marker=is-name',
|
||||
)
|
||||
self.assertEqual(data, resp)
|
@ -71,6 +71,7 @@ class TestCommand(TestCase):
|
||||
self.fake_stdout = fakes.FakeStdout()
|
||||
self.app = fakes.FakeApp(self.fake_stdout)
|
||||
self.app.client_manager = fakes.FakeClientManager()
|
||||
self.app.restapi = fakes.FakeRESTApi()
|
||||
|
||||
def check_parser(self, cmd, args, verify_args):
|
||||
cmd_parser = cmd.get_parser('check_parser')
|
||||
|
@ -239,6 +239,10 @@ openstack.compute.v2 =
|
||||
server_unrescue = openstackclient.compute.v2.server:UnrescueServer
|
||||
server_unset = openstackclient.compute.v2.server:UnsetServer
|
||||
|
||||
openstack.object_store.v1 =
|
||||
container_list = openstackclient.object.v1.container:ListContainer
|
||||
object_list = openstackclient.object.v1.object:ListObject
|
||||
|
||||
openstack.volume.v1 =
|
||||
snapshot_create = openstackclient.volume.v1.snapshot:CreateSnapshot
|
||||
snapshot_delete = openstackclient.volume.v1.snapshot:DeleteSnapshot
|
||||
|
Loading…
x
Reference in New Issue
Block a user