Skip to content

Commit 725e254

Browse files
author
Dean Troyer
committed
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
1 parent 17f13f7 commit 725e254

21 files changed

Lines changed: 1653 additions & 2 deletions

openstackclient/common/clientmanager.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from openstackclient.compute import client as compute_client
2121
from openstackclient.identity import client as identity_client
2222
from openstackclient.image import client as image_client
23+
from openstackclient.object import client as object_client
2324
from openstackclient.volume import client as volume_client
2425

2526

@@ -44,6 +45,7 @@ class ClientManager(object):
4445
compute = ClientCache(compute_client.make_client)
4546
identity = ClientCache(identity_client.make_client)
4647
image = ClientCache(image_client.make_client)
48+
object = ClientCache(object_client.make_client)
4749
volume = ClientCache(volume_client.make_client)
4850

4951
def __init__(self, token=None, url=None, auth_url=None, project_name=None,

openstackclient/object/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#

openstackclient/object/client.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Copyright 2013 Nebula Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
"""Object client"""
17+
18+
import logging
19+
20+
from openstackclient.common import utils
21+
22+
LOG = logging.getLogger(__name__)
23+
24+
API_NAME = 'object-store'
25+
API_VERSIONS = {
26+
'1': 'openstackclient.object.client.ObjectClientv1',
27+
}
28+
29+
30+
def make_client(instance):
31+
"""Returns an object service client."""
32+
object_client = utils.get_client_class(
33+
API_NAME,
34+
instance._api_version[API_NAME],
35+
API_VERSIONS)
36+
if instance._url:
37+
endpoint = instance._url
38+
else:
39+
endpoint = instance.get_endpoint_for_service_type(API_NAME)
40+
LOG.debug('instantiating object client')
41+
client = object_client(
42+
endpoint=endpoint,
43+
token=instance._token,
44+
)
45+
return client
46+
47+
48+
class ObjectClientv1(object):
49+
50+
def __init__(
51+
self,
52+
endpoint_type='publicURL',
53+
endpoint=None,
54+
token=None,
55+
):
56+
self.endpoint_type = endpoint_type
57+
self.endpoint = endpoint
58+
self.token = token
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Copyright 2013 Nebula Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
# not use this file except in compliance with the License. You may obtain
5+
# a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
#
15+
16+
"""Container v1 action implementations"""
17+
18+
19+
import logging
20+
21+
from cliff import lister
22+
23+
from openstackclient.common import utils
24+
from openstackclient.object.v1.lib import container as lib_container
25+
26+
27+
class ListContainer(lister.Lister):
28+
"""List containers"""
29+
30+
log = logging.getLogger(__name__ + '.ListContainer')
31+
32+
def get_parser(self, prog_name):
33+
parser = super(ListContainer, self).get_parser(prog_name)
34+
parser.add_argument(
35+
"--prefix",
36+
metavar="<prefix>",
37+
help="Filter list using <prefix>",
38+
)
39+
parser.add_argument(
40+
"--marker",
41+
metavar="<marker>",
42+
help="Anchor for paging",
43+
)
44+
parser.add_argument(
45+
"--end-marker",
46+
metavar="<end-marker>",
47+
help="End anchor for paging",
48+
)
49+
parser.add_argument(
50+
"--limit",
51+
metavar="<limit>",
52+
type=int,
53+
help="Limit the number of containers returned",
54+
)
55+
parser.add_argument(
56+
'--long',
57+
action='store_true',
58+
default=False,
59+
help='List additional fields in output',
60+
)
61+
parser.add_argument(
62+
'--all',
63+
action='store_true',
64+
default=False,
65+
help='List all containers (default is 10000)',
66+
)
67+
return parser
68+
69+
def take_action(self, parsed_args):
70+
self.log.debug('take_action(%s)' % parsed_args)
71+
72+
if parsed_args.long:
73+
columns = ('Name', 'Bytes', 'Count')
74+
else:
75+
columns = ('Name',)
76+
77+
kwargs = {}
78+
if parsed_args.prefix:
79+
kwargs['prefix'] = parsed_args.prefix
80+
if parsed_args.marker:
81+
kwargs['marker'] = parsed_args.marker
82+
if parsed_args.end_marker:
83+
kwargs['end_marker'] = parsed_args.end_marker
84+
if parsed_args.limit:
85+
kwargs['limit'] = parsed_args.limit
86+
if parsed_args.all:
87+
kwargs['full_listing'] = True
88+
89+
data = lib_container.list_containers(
90+
self.app.restapi,
91+
self.app.client_manager.object.endpoint,
92+
**kwargs
93+
)
94+
#print "data: %s" % data
95+
96+
return (columns,
97+
(utils.get_dict_properties(
98+
s, columns,
99+
formatters={},
100+
) for s in data))
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
2+
# not use this file except in compliance with the License. You may obtain
3+
# a copy of the License at
4+
#
5+
# http://www.apache.org/licenses/LICENSE-2.0
6+
#
7+
# Unless required by applicable law or agreed to in writing, software
8+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10+
# License for the specific language governing permissions and limitations
11+
# under the License.
12+
#
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright 2010-2012 OpenStack Foundation
2+
# Copyright 2013 Nebula Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
#
16+
17+
"""Object v1 API library"""
18+
19+
20+
def list_containers(
21+
api,
22+
url,
23+
marker=None,
24+
limit=None,
25+
end_marker=None,
26+
prefix=None,
27+
full_listing=False,
28+
):
29+
"""Get containers in an account
30+
31+
:param api: a restapi object
32+
:param url: endpoint
33+
:param marker: marker query
34+
:param limit: limit query
35+
:param end_marker: end_marker query
36+
:param prefix: prefix query
37+
:param full_listing: if True, return a full listing, else returns a max
38+
of 10000 listings
39+
:returns: list of containers
40+
"""
41+
42+
if full_listing:
43+
data = listing = list_containers(
44+
api,
45+
url,
46+
marker,
47+
limit,
48+
end_marker,
49+
prefix,
50+
)
51+
while listing:
52+
marker = listing[-1]['name']
53+
listing = list_containers(
54+
api,
55+
url,
56+
marker,
57+
limit,
58+
end_marker,
59+
prefix,
60+
)
61+
if listing:
62+
data.extend(listing)
63+
return data
64+
65+
object_url = url
66+
query = "format=json"
67+
if marker:
68+
query += '&marker=%s' % marker
69+
if limit:
70+
query += '&limit=%d' % limit
71+
if end_marker:
72+
query += '&end_marker=%s' % end_marker
73+
if prefix:
74+
query += '&prefix=%s' % prefix
75+
url = "%s?%s" % (object_url, query)
76+
response = api.request('GET', url)
77+
return response.json()
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# Copyright 2010-2012 OpenStack Foundation
2+
# Copyright 2013 Nebula Inc.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
#
16+
17+
"""Object v1 API library"""
18+
19+
20+
def list_objects(
21+
api,
22+
url,
23+
container,
24+
marker=None,
25+
limit=None,
26+
end_marker=None,
27+
delimiter=None,
28+
prefix=None,
29+
path=None,
30+
full_listing=False,
31+
):
32+
"""Get objects in a container
33+
34+
:param api: a restapi object
35+
:param url: endpoint
36+
:param container: container name to get a listing for
37+
:param marker: marker query
38+
:param limit: limit query
39+
:param end_marker: marker query
40+
:param delimiter: string to delimit the queries on
41+
:param prefix: prefix query
42+
:param path: path query (equivalent: "delimiter=/" and "prefix=path/")
43+
:param full_listing: if True, return a full listing, else returns a max
44+
of 10000 listings
45+
:returns: a tuple of (response headers, a list of objects) The response
46+
headers will be a dict and all header names will be lowercase.
47+
"""
48+
49+
if full_listing:
50+
data = listing = list_objects(
51+
api,
52+
url,
53+
container,
54+
marker,
55+
limit,
56+
end_marker,
57+
delimiter,
58+
prefix,
59+
path,
60+
)
61+
while listing:
62+
if delimiter:
63+
marker = listing[-1].get('name', listing[-1].get('subdir'))
64+
else:
65+
marker = listing[-1]['name']
66+
listing = list_objects(
67+
api,
68+
url,
69+
container,
70+
marker,
71+
limit,
72+
end_marker,
73+
delimiter,
74+
prefix,
75+
path,
76+
)
77+
if listing:
78+
data.extend(listing)
79+
return data
80+
81+
object_url = url
82+
query = "format=json"
83+
if marker:
84+
query += '&marker=%s' % marker
85+
if limit:
86+
query += '&limit=%d' % limit
87+
if end_marker:
88+
query += '&end_marker=%s' % end_marker
89+
if delimiter:
90+
query += '&delimiter=%s' % delimiter
91+
if prefix:
92+
query += '&prefix=%s' % prefix
93+
if path:
94+
query += '&path=%s' % path
95+
url = "%s/%s?%s" % (object_url, container, query)
96+
response = api.request('GET', url)
97+
return response.json()

0 commit comments

Comments
 (0)