Add storage policy option to create container command

+ Add CLI option to specify swift storage policy
 + Add CLI flag to specify container uses public read ACLS
 + Show storage policy in container show data

Change-Id: I08ffa0d98bd39d467aa415771675f59bd77768ff
This commit is contained in:
Simon Merrick 2020-02-18 12:48:02 +13:00
parent e07324e30f
commit d6022f96df
4 changed files with 111 additions and 2 deletions

View File

@ -24,6 +24,11 @@ from six.moves import urllib
from openstackclient.api import api from openstackclient.api import api
GLOBAL_READ_ACL = ".r:*"
LIST_CONTENTS_ACL = ".rlistings"
PUBLIC_CONTAINER_ACLS = [GLOBAL_READ_ACL, LIST_CONTENTS_ACL]
class APIv1(api.BaseAPI): class APIv1(api.BaseAPI):
"""Object Store v1 API""" """Object Store v1 API"""
@ -33,15 +38,32 @@ class APIv1(api.BaseAPI):
def container_create( def container_create(
self, self,
container=None, container=None,
public=False,
storage_policy=None
): ):
"""Create a container """Create a container
:param string container: :param string container:
name of container to create name of container to create
:param bool public:
Boolean value indicating if the container should be publicly
readable. Defaults to False.
:param string storage_policy:
Name of the a specific storage policy to use. If not specified
swift will use its default storage policy.
:returns: :returns:
dict of returned headers dict of returned headers
""" """
response = self.create(urllib.parse.quote(container), method='PUT')
headers = {}
if public:
headers['x-container-read'] = ",".join(PUBLIC_CONTAINER_ACLS)
if storage_policy is not None:
headers['x-storage-policy'] = storage_policy
response = self.create(
urllib.parse.quote(container), method='PUT', headers=headers)
data = { data = {
'account': self._find_account_id(), 'account': self._find_account_id(),
'container': container, 'container': container,
@ -173,7 +195,8 @@ class APIv1(api.BaseAPI):
'object_count': response.headers.get( 'object_count': response.headers.get(
'x-container-object-count' 'x-container-object-count'
), ),
'bytes_used': response.headers.get('x-container-bytes-used') 'bytes_used': response.headers.get('x-container-bytes-used'),
'storage_policy': response.headers.get('x-storage-policy'),
} }
if 'x-container-read' in response.headers: if 'x-container-read' in response.headers:

View File

@ -33,6 +33,16 @@ class CreateContainer(command.Lister):
def get_parser(self, prog_name): def get_parser(self, prog_name):
parser = super(CreateContainer, self).get_parser(prog_name) parser = super(CreateContainer, self).get_parser(prog_name)
parser.add_argument(
'--public',
action='store_true',
default=False,
help="Make the container publicly accessible"
)
parser.add_argument(
'--storage-policy',
help="Specify a particular storage policy to use."
)
parser.add_argument( parser.add_argument(
'containers', 'containers',
metavar='<container-name>', metavar='<container-name>',
@ -51,6 +61,8 @@ class CreateContainer(command.Lister):
' is 256'), len(container)) ' is 256'), len(container))
data = self.app.client_manager.object_store.container_create( data = self.app.client_manager.object_store.container_create(
container=container, container=container,
public=parsed_args.public,
storage_policy=parsed_args.storage_policy
) )
results.append(data) results.append(data)

View File

@ -151,12 +151,14 @@ class TestContainer(TestObjectAPIv1):
'X-Container-Meta-Owner': FAKE_ACCOUNT, 'X-Container-Meta-Owner': FAKE_ACCOUNT,
'x-container-object-count': '1', 'x-container-object-count': '1',
'x-container-bytes-used': '577', 'x-container-bytes-used': '577',
'x-storage-policy': 'o1--sr-r3'
} }
resp = { resp = {
'account': FAKE_ACCOUNT, 'account': FAKE_ACCOUNT,
'container': 'qaz', 'container': 'qaz',
'object_count': '1', 'object_count': '1',
'bytes_used': '577', 'bytes_used': '577',
'storage_policy': 'o1--sr-r3',
'properties': {'Owner': FAKE_ACCOUNT}, 'properties': {'Owner': FAKE_ACCOUNT},
} }
self.requests_mock.register_uri( self.requests_mock.register_uri(

View File

@ -70,6 +70,75 @@ class TestContainerCreate(TestContainerAll):
)] )]
self.assertEqual(datalist, list(data)) self.assertEqual(datalist, list(data))
def test_object_create_container_storage_policy(self):
self.requests_mock.register_uri(
'PUT',
object_fakes.ENDPOINT + '/ernie',
headers={
'x-trans-id': '314159',
'x-storage-policy': 'o1--sr-r3'
},
status_code=200,
)
arglist = [
'ernie',
'--storage-policy',
'o1--sr-r3'
]
verifylist = [
('containers', ['ernie']),
('storage_policy', 'o1--sr-r3')
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
self.assertEqual(self.columns, columns)
datalist = [(
object_fakes.ACCOUNT_ID,
'ernie',
'314159',
)]
self.assertEqual(datalist, list(data))
def test_object_create_container_public(self):
self.requests_mock.register_uri(
'PUT',
object_fakes.ENDPOINT + '/ernie',
headers={
'x-trans-id': '314159',
'x-container-read': '.r:*,.rlistings'
},
status_code=200,
)
arglist = [
'ernie',
'--public'
]
verifylist = [
('containers', ['ernie']),
('public', True)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
# In base command class ShowOne in cliff, abstract method take_action()
# returns a two-part tuple with a tuple of column names and a tuple of
# data to be shown.
columns, data = self.cmd.take_action(parsed_args)
self.assertEqual(self.columns, columns)
datalist = [(
object_fakes.ACCOUNT_ID,
'ernie',
'314159',
)]
self.assertEqual(datalist, list(data))
def test_object_create_container_more(self): def test_object_create_container_more(self):
self.requests_mock.register_uri( self.requests_mock.register_uri(
'PUT', 'PUT',
@ -300,6 +369,7 @@ class TestContainerShow(TestContainerAll):
'x-container-write': 'wsx', 'x-container-write': 'wsx',
'x-container-sync-to': 'edc', 'x-container-sync-to': 'edc',
'x-container-sync-key': 'rfv', 'x-container-sync-key': 'rfv',
'x-storage-policy': 'o1--sr-r3'
} }
self.requests_mock.register_uri( self.requests_mock.register_uri(
'HEAD', 'HEAD',
@ -327,6 +397,7 @@ class TestContainerShow(TestContainerAll):
'container', 'container',
'object_count', 'object_count',
'read_acl', 'read_acl',
'storage_policy',
'sync_key', 'sync_key',
'sync_to', 'sync_to',
'write_acl', 'write_acl',
@ -338,6 +409,7 @@ class TestContainerShow(TestContainerAll):
'ernie', 'ernie',
'42', '42',
'qaz', 'qaz',
'o1--sr-r3',
'rfv', 'rfv',
'edc', 'edc',
'wsx', 'wsx',