Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / qa / tasks / radosgw_admin_rest.py
1 """
2 Run a series of rgw admin commands through the rest interface.
3
4 The test cases in this file have been annotated for inventory.
5 To extract the inventory (in csv format) use the command:
6
7    grep '^ *# TESTCASE' | sed 's/^ *# TESTCASE //'
8
9 """
10 from cStringIO import StringIO
11 import logging
12 import json
13
14 import boto.exception
15 import boto.s3.connection
16 import boto.s3.acl
17
18 import requests
19 import time
20
21 from boto.connection import AWSAuthConnection
22 from teuthology import misc as teuthology
23 from util.rgw import get_user_summary, get_user_successful_ops
24
25 log = logging.getLogger(__name__)
26
27 def rgwadmin(ctx, client, cmd):
28     """
29     Perform rgw admin command
30
31     :param client: client
32     :param cmd: command to execute.
33     :return: command exit status, json result.
34     """
35     log.info('radosgw-admin: %s' % cmd)
36     testdir = teuthology.get_testdir(ctx)
37     pre = [
38         'adjust-ulimits',
39         'ceph-coverage',
40         '{tdir}/archive/coverage'.format(tdir=testdir),
41         'radosgw-admin',
42         '--log-to-stderr',
43         '--format', 'json',
44         ]
45     pre.extend(cmd)
46     (remote,) = ctx.cluster.only(client).remotes.iterkeys()
47     proc = remote.run(
48         args=pre,
49         check_status=False,
50         stdout=StringIO(),
51         stderr=StringIO(),
52         )
53     r = proc.exitstatus
54     out = proc.stdout.getvalue()
55     j = None
56     if not r and out != '':
57         try:
58             j = json.loads(out)
59             log.info(' json result: %s' % j)
60         except ValueError:
61             j = out
62             log.info(' raw result: %s' % j)
63     return (r, j)
64
65
66 def rgwadmin_rest(connection, cmd, params=None, headers=None, raw=False):
67     """
68     perform a rest command
69     """
70     log.info('radosgw-admin-rest: %s %s' % (cmd, params))
71     put_cmds = ['create', 'link', 'add']
72     post_cmds = ['unlink', 'modify']
73     delete_cmds = ['trim', 'rm', 'process']
74     get_cmds = ['check', 'info', 'show', 'list']
75
76     bucket_sub_resources = ['object', 'policy', 'index']
77     user_sub_resources = ['subuser', 'key', 'caps']
78     zone_sub_resources = ['pool', 'log', 'garbage']
79
80     def get_cmd_method_and_handler(cmd):
81         """
82         Get the rest command and handler from information in cmd and
83         from the imported requests object.
84         """
85         if cmd[1] in put_cmds:
86             return 'PUT', requests.put
87         elif cmd[1] in delete_cmds:
88             return 'DELETE', requests.delete
89         elif cmd[1] in post_cmds:
90             return 'POST', requests.post
91         elif cmd[1] in get_cmds:
92             return 'GET', requests.get
93
94     def get_resource(cmd):
95         """
96         Get the name of the resource from information in cmd.
97         """
98         if cmd[0] == 'bucket' or cmd[0] in bucket_sub_resources:
99             if cmd[0] == 'bucket':
100                 return 'bucket', ''
101             else:
102                 return 'bucket', cmd[0]
103         elif cmd[0] == 'user' or cmd[0] in user_sub_resources:
104             if cmd[0] == 'user':
105                 return 'user', ''
106             else:
107                 return 'user', cmd[0]
108         elif cmd[0] == 'usage':
109             return 'usage', ''
110         elif cmd[0] == 'zone' or cmd[0] in zone_sub_resources:
111             if cmd[0] == 'zone':
112                 return 'zone', ''
113             else:
114                 return 'zone', cmd[0]
115
116     def build_admin_request(conn, method, resource = '', headers=None, data='',
117             query_args=None, params=None):
118         """
119         Build an administative request adapted from the build_request()
120         method of boto.connection
121         """
122
123         path = conn.calling_format.build_path_base('admin', resource)
124         auth_path = conn.calling_format.build_auth_path('admin', resource)
125         host = conn.calling_format.build_host(conn.server_name(), 'admin')
126         if query_args:
127             path += '?' + query_args
128             boto.log.debug('path=%s' % path)
129             auth_path += '?' + query_args
130             boto.log.debug('auth_path=%s' % auth_path)
131         return AWSAuthConnection.build_base_http_request(conn, method, path,
132                 auth_path, params, headers, data, host)
133
134     method, handler = get_cmd_method_and_handler(cmd)
135     resource, query_args = get_resource(cmd)
136     request = build_admin_request(connection, method, resource,
137             query_args=query_args, headers=headers)
138
139     url = '{protocol}://{host}{path}'.format(protocol=request.protocol,
140             host=request.host, path=request.path)
141
142     request.authorize(connection=connection)
143     result = handler(url, params=params, headers=request.headers)
144
145     if raw:
146         log.info(' text result: %s' % result.txt)
147         return result.status_code, result.txt
148     else:
149         log.info(' json result: %s' % result.json())
150         return result.status_code, result.json()
151
152
153 def task(ctx, config):
154     """
155     Test radosgw-admin functionality through the RESTful interface
156     """
157     assert config is None or isinstance(config, list) \
158         or isinstance(config, dict), \
159         "task s3tests only supports a list or dictionary for configuration"
160     all_clients = ['client.{id}'.format(id=id_)
161                    for id_ in teuthology.all_roles_of_type(ctx.cluster, 'client')]
162     if config is None:
163         config = all_clients
164     if isinstance(config, list):
165         config = dict.fromkeys(config)
166     clients = config.keys()
167
168     # just use the first client...
169     client = clients[0]
170
171     ##
172     admin_user = 'ada'
173     admin_display_name = 'Ms. Admin User'
174     admin_access_key = 'MH1WC2XQ1S8UISFDZC8W'
175     admin_secret_key = 'dQyrTPA0s248YeN5bBv4ukvKU0kh54LWWywkrpoG'
176     admin_caps = 'users=read, write; usage=read, write; buckets=read, write; zone=read, write'
177
178     user1 = 'foo'
179     user2 = 'fud'
180     subuser1 = 'foo:foo1'
181     subuser2 = 'foo:foo2'
182     display_name1 = 'Foo'
183     display_name2 = 'Fud'
184     email = 'foo@foo.com'
185     access_key = '9te6NH5mcdcq0Tc5i8i1'
186     secret_key = 'Ny4IOauQoL18Gp2zM7lC1vLmoawgqcYP/YGcWfXu'
187     access_key2 = 'p5YnriCv1nAtykxBrupQ'
188     secret_key2 = 'Q8Tk6Q/27hfbFSYdSkPtUqhqx1GgzvpXa4WARozh'
189     swift_secret1 = 'gpS2G9RREMrnbqlp29PP2D36kgPR1tm72n5fPYfL'
190     swift_secret2 = 'ri2VJQcKSYATOY6uaDUX7pxgkW+W1YmC6OCxPHwy'
191
192     bucket_name = 'myfoo'
193
194     # legend (test cases can be easily grep-ed out)
195     # TESTCASE 'testname','object','method','operation','assertion'
196     # TESTCASE 'create-admin-user','user','create','administrative user','succeeds'
197     (err, out) = rgwadmin(ctx, client, [
198             'user', 'create',
199             '--uid', admin_user,
200             '--display-name', admin_display_name,
201             '--access-key', admin_access_key,
202             '--secret', admin_secret_key,
203             '--max-buckets', '0',
204             '--caps', admin_caps
205             ])
206     logging.error(out)
207     logging.error(err)
208     assert not err
209
210     (remote,) = ctx.cluster.only(client).remotes.iterkeys()
211     remote_host = remote.name.split('@')[1]
212     admin_conn = boto.s3.connection.S3Connection(
213         aws_access_key_id=admin_access_key,
214         aws_secret_access_key=admin_secret_key,
215         is_secure=False,
216         port=7280,
217         host=remote_host,
218         calling_format=boto.s3.connection.OrdinaryCallingFormat(),
219         )
220
221     # TESTCASE 'info-nosuch','user','info','non-existent user','fails'
222     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {"uid": user1})
223     assert ret == 404
224
225     # TESTCASE 'create-ok','user','create','w/all valid info','succeeds'
226     (ret, out) = rgwadmin_rest(admin_conn,
227             ['user', 'create'],
228             {'uid' : user1,
229              'display-name' :  display_name1,
230              'email' : email,
231              'access-key' : access_key,
232              'secret-key' : secret_key,
233              'max-buckets' : '4'
234             })
235
236     assert ret == 200
237
238     # TESTCASE 'info-existing','user','info','existing user','returns correct info'
239     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
240
241     assert out['user_id'] == user1
242     assert out['email'] == email
243     assert out['display_name'] == display_name1
244     assert len(out['keys']) == 1
245     assert out['keys'][0]['access_key'] == access_key
246     assert out['keys'][0]['secret_key'] == secret_key
247     assert not out['suspended']
248
249     # TESTCASE 'suspend-ok','user','suspend','active user','succeeds'
250     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'modify'], {'uid' : user1, 'suspended' : True})
251     assert ret == 200
252
253     # TESTCASE 'suspend-suspended','user','suspend','suspended user','succeeds w/advisory'
254     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
255     assert ret == 200
256     assert out['suspended']
257
258     # TESTCASE 're-enable','user','enable','suspended user','succeeds'
259     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'modify'], {'uid' : user1, 'suspended' : 'false'})
260     assert not err
261
262     # TESTCASE 'info-re-enabled','user','info','re-enabled user','no longer suspended'
263     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
264     assert ret == 200
265     assert not out['suspended']
266
267     # TESTCASE 'add-keys','key','create','w/valid info','succeeds'
268     (ret, out) = rgwadmin_rest(admin_conn,
269             ['key', 'create'],
270             {'uid' : user1,
271              'access-key' : access_key2,
272              'secret-key' : secret_key2
273             })
274
275
276     assert ret == 200
277
278     # TESTCASE 'info-new-key','user','info','after key addition','returns all keys'
279     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
280     assert ret == 200
281     assert len(out['keys']) == 2
282     assert out['keys'][0]['access_key'] == access_key2 or out['keys'][1]['access_key'] == access_key2
283     assert out['keys'][0]['secret_key'] == secret_key2 or out['keys'][1]['secret_key'] == secret_key2
284
285     # TESTCASE 'rm-key','key','rm','newly added key','succeeds, key is removed'
286     (ret, out) = rgwadmin_rest(admin_conn,
287             ['key', 'rm'],
288             {'uid' : user1,
289              'access-key' : access_key2
290             })
291
292     assert ret == 200
293
294     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
295
296     assert len(out['keys']) == 1
297     assert out['keys'][0]['access_key'] == access_key
298     assert out['keys'][0]['secret_key'] == secret_key
299
300     # TESTCASE 'add-swift-key','key','create','swift key','succeeds'
301     (ret, out) = rgwadmin_rest(admin_conn,
302             ['subuser', 'create'],
303             {'subuser' : subuser1,
304              'secret-key' : swift_secret1,
305              'key-type' : 'swift'
306             })
307
308     assert ret == 200
309
310     # TESTCASE 'info-swift-key','user','info','after key addition','returns all keys'
311     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' : user1})
312     assert ret == 200
313     assert len(out['swift_keys']) == 1
314     assert out['swift_keys'][0]['user'] == subuser1
315     assert out['swift_keys'][0]['secret_key'] == swift_secret1
316
317     # TESTCASE 'add-swift-subuser','key','create','swift sub-user key','succeeds'
318     (ret, out) = rgwadmin_rest(admin_conn,
319             ['subuser', 'create'],
320             {'subuser' : subuser2,
321              'secret-key' : swift_secret2,
322              'key-type' : 'swift'
323             })
324
325     assert ret == 200
326
327     # TESTCASE 'info-swift-subuser','user','info','after key addition','returns all sub-users/keys'
328     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' :  user1})
329     assert ret == 200
330     assert len(out['swift_keys']) == 2
331     assert out['swift_keys'][0]['user'] == subuser2 or out['swift_keys'][1]['user'] == subuser2
332     assert out['swift_keys'][0]['secret_key'] == swift_secret2 or out['swift_keys'][1]['secret_key'] == swift_secret2
333
334     # TESTCASE 'rm-swift-key1','key','rm','subuser','succeeds, one key is removed'
335     (ret, out) = rgwadmin_rest(admin_conn,
336             ['key', 'rm'],
337             {'subuser' : subuser1,
338              'key-type' :'swift'
339             })
340
341     assert ret == 200
342
343     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' :  user1})
344     assert len(out['swift_keys']) == 1
345
346     # TESTCASE 'rm-subuser','subuser','rm','subuser','success, subuser is removed'
347     (ret, out) = rgwadmin_rest(admin_conn,
348             ['subuser', 'rm'],
349             {'subuser' : subuser1
350             })
351
352     assert ret == 200
353
354     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' :  user1})
355     assert len(out['subusers']) == 1
356
357     # TESTCASE 'rm-subuser-with-keys','subuser','rm','subuser','succeeds, second subser and key is removed'
358     (ret, out) = rgwadmin_rest(admin_conn,
359             ['subuser', 'rm'],
360             {'subuser' : subuser2,
361              'key-type' : 'swift',
362              '{purge-keys' :True
363             })
364
365     assert ret == 200
366
367     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' :  user1})
368     assert len(out['swift_keys']) == 0
369     assert len(out['subusers']) == 0
370
371     # TESTCASE 'bucket-stats','bucket','info','no session/buckets','succeeds, empty list'
372     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'info'], {'uid' :  user1})
373     assert ret == 200
374     assert len(out) == 0
375
376     # connect to rgw
377     connection = boto.s3.connection.S3Connection(
378         aws_access_key_id=access_key,
379         aws_secret_access_key=secret_key,
380         is_secure=False,
381         port=7280,
382         host=remote_host,
383         calling_format=boto.s3.connection.OrdinaryCallingFormat(),
384         )
385
386     # TESTCASE 'bucket-stats2','bucket','stats','no buckets','succeeds, empty list'
387     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'info'], {'uid' : user1, 'stats' : True})
388     assert ret == 200
389     assert len(out) == 0
390
391     # create a first bucket
392     bucket = connection.create_bucket(bucket_name)
393
394     # TESTCASE 'bucket-list','bucket','list','one bucket','succeeds, expected list'
395     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'info'], {'uid' : user1})
396     assert ret == 200
397     assert len(out) == 1
398     assert out[0] == bucket_name
399
400     # TESTCASE 'bucket-stats3','bucket','stats','new empty bucket','succeeds, empty list'
401     (ret, out) = rgwadmin_rest(admin_conn,
402             ['bucket', 'info'], {'bucket' : bucket_name, 'stats' : True})
403
404     assert ret == 200
405     assert out['owner'] == user1
406     bucket_id = out['id']
407
408     # TESTCASE 'bucket-stats4','bucket','stats','new empty bucket','succeeds, expected bucket ID'
409     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'info'], {'uid' : user1, 'stats' : True})
410     assert ret == 200
411     assert len(out) == 1
412     assert out[0]['id'] == bucket_id    # does it return the same ID twice in a row?
413
414     # use some space
415     key = boto.s3.key.Key(bucket)
416     key.set_contents_from_string('one')
417
418     # TESTCASE 'bucket-stats5','bucket','stats','after creating key','succeeds, lists one non-empty object'
419     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'info'], {'bucket' : bucket_name, 'stats' : True})
420     assert ret == 200
421     assert out['id'] == bucket_id
422     assert out['usage']['rgw.main']['num_objects'] == 1
423     assert out['usage']['rgw.main']['size_kb'] > 0
424
425     # reclaim it
426     key.delete()
427
428     # TESTCASE 'bucket unlink', 'bucket', 'unlink', 'unlink bucket from user', 'fails', 'access denied error'
429     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'unlink'], {'uid' : user1, 'bucket' : bucket_name})
430
431     assert ret == 200
432
433     # create a second user to link the bucket to
434     (ret, out) = rgwadmin_rest(admin_conn,
435             ['user', 'create'],
436             {'uid' : user2,
437             'display-name' :  display_name2,
438             'access-key' : access_key2,
439             'secret-key' : secret_key2,
440             'max-buckets' : '1',
441             })
442
443     assert ret == 200
444
445     # try creating an object with the first user before the bucket is relinked
446     denied = False
447     key = boto.s3.key.Key(bucket)
448
449     try:
450         key.set_contents_from_string('two')
451     except boto.exception.S3ResponseError:
452         denied = True
453
454     assert not denied
455
456     # delete the object
457     key.delete()
458
459     # link the bucket to another user
460     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'link'], {'uid' : user2, 'bucket' : bucket_name})
461
462     assert ret == 200
463
464     # try creating an object with the first user which should cause an error
465     key = boto.s3.key.Key(bucket)
466
467     try:
468         key.set_contents_from_string('three')
469     except boto.exception.S3ResponseError:
470         denied = True
471
472     assert denied
473
474     # relink the bucket to the first user and delete the second user
475     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'link'], {'uid' : user1, 'bucket' : bucket_name})
476     assert ret == 200
477
478     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'rm'], {'uid' : user2})
479     assert ret == 200
480
481     # TESTCASE 'object-rm', 'object', 'rm', 'remove object', 'succeeds, object is removed'
482
483     # upload an object
484     object_name = 'four'
485     key = boto.s3.key.Key(bucket, object_name)
486     key.set_contents_from_string(object_name)
487
488     # now delete it
489     (ret, out) = rgwadmin_rest(admin_conn, ['object', 'rm'], {'bucket' : bucket_name, 'object' : object_name})
490     assert ret == 200
491
492     # TESTCASE 'bucket-stats6','bucket','stats','after deleting key','succeeds, lists one no objects'
493     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'info'], {'bucket' : bucket_name, 'stats' : True})
494     assert ret == 200
495     assert out['id'] == bucket_id
496     assert out['usage']['rgw.main']['num_objects'] == 0
497
498     # create a bucket for deletion stats
499     useless_bucket = connection.create_bucket('useless_bucket')
500     useless_key = useless_bucket.new_key('useless_key')
501     useless_key.set_contents_from_string('useless string')
502
503     # delete it
504     useless_key.delete()
505     useless_bucket.delete()
506
507     # wait for the statistics to flush
508     time.sleep(60)
509
510     # need to wait for all usage data to get flushed, should take up to 30 seconds
511     timestamp = time.time()
512     while time.time() - timestamp <= (20 * 60):      # wait up to 20 minutes
513         (ret, out) = rgwadmin_rest(admin_conn, ['usage', 'show'], {'categories' : 'delete_obj'})  # last operation we did is delete obj, wait for it to flush
514
515         if get_user_successful_ops(out, user1) > 0:
516             break
517         time.sleep(1)
518
519     assert time.time() - timestamp <= (20 * 60)
520
521     # TESTCASE 'usage-show' 'usage' 'show' 'all usage' 'succeeds'
522     (ret, out) = rgwadmin_rest(admin_conn, ['usage', 'show'])
523     assert ret == 200
524     assert len(out['entries']) > 0
525     assert len(out['summary']) > 0
526     user_summary = get_user_summary(out, user1)
527     total = user_summary['total']
528     assert total['successful_ops'] > 0
529
530     # TESTCASE 'usage-show2' 'usage' 'show' 'user usage' 'succeeds'
531     (ret, out) = rgwadmin_rest(admin_conn, ['usage', 'show'], {'uid' : user1})
532     assert ret == 200
533     assert len(out['entries']) > 0
534     assert len(out['summary']) > 0
535     user_summary = out['summary'][0]
536     for entry in user_summary['categories']:
537         assert entry['successful_ops'] > 0
538     assert user_summary['user'] == user1
539
540     # TESTCASE 'usage-show3' 'usage' 'show' 'user usage categories' 'succeeds'
541     test_categories = ['create_bucket', 'put_obj', 'delete_obj', 'delete_bucket']
542     for cat in test_categories:
543         (ret, out) = rgwadmin_rest(admin_conn, ['usage', 'show'], {'uid' : user1, 'categories' : cat})
544         assert ret == 200
545         assert len(out['summary']) > 0
546         user_summary = out['summary'][0]
547         assert user_summary['user'] == user1
548         assert len(user_summary['categories']) == 1
549         entry = user_summary['categories'][0]
550         assert entry['category'] == cat
551         assert entry['successful_ops'] > 0
552
553     # TESTCASE 'usage-trim' 'usage' 'trim' 'user usage' 'succeeds, usage removed'
554     (ret, out) = rgwadmin_rest(admin_conn, ['usage', 'trim'], {'uid' : user1})
555     assert ret == 200
556     (ret, out) = rgwadmin_rest(admin_conn, ['usage', 'show'], {'uid' : user1})
557     assert ret == 200
558     assert len(out['entries']) == 0
559     assert len(out['summary']) == 0
560
561     # TESTCASE 'user-suspend2','user','suspend','existing user','succeeds'
562     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'modify'], {'uid' : user1, 'suspended' : True})
563     assert ret == 200
564
565     # TESTCASE 'user-suspend3','user','suspend','suspended user','cannot write objects'
566     try:
567         key = boto.s3.key.Key(bucket)
568         key.set_contents_from_string('five')
569     except boto.exception.S3ResponseError as e:
570         assert e.status == 403
571
572     # TESTCASE 'user-renable2','user','enable','suspended user','succeeds'
573     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'modify'], {'uid' :  user1, 'suspended' : 'false'})
574     assert ret == 200
575
576     # TESTCASE 'user-renable3','user','enable','reenabled user','can write objects'
577     key = boto.s3.key.Key(bucket)
578     key.set_contents_from_string('six')
579
580     # TESTCASE 'garbage-list', 'garbage', 'list', 'get list of objects ready for garbage collection'
581
582     # create an object large enough to be split into multiple parts
583     test_string = 'foo'*10000000
584
585     big_key = boto.s3.key.Key(bucket)
586     big_key.set_contents_from_string(test_string)
587
588     # now delete the head
589     big_key.delete()
590
591     # TESTCASE 'rm-user-buckets','user','rm','existing user','fails, still has buckets'
592     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'rm'], {'uid' : user1})
593     assert ret == 409
594
595     # delete should fail because ``key`` still exists
596     try:
597         bucket.delete()
598     except boto.exception.S3ResponseError as e:
599         assert e.status == 409
600
601     key.delete()
602     bucket.delete()
603
604     # TESTCASE 'policy', 'bucket', 'policy', 'get bucket policy', 'returns S3 policy'
605     bucket = connection.create_bucket(bucket_name)
606
607     # create an object
608     key = boto.s3.key.Key(bucket)
609     key.set_contents_from_string('seven')
610
611     # should be private already but guarantee it
612     key.set_acl('private')
613
614     (ret, out) = rgwadmin_rest(admin_conn, ['policy', 'show'], {'bucket' : bucket.name, 'object' : key.key})
615     assert ret == 200
616
617     acl = key.get_xml_acl()
618     assert acl == out.strip('\n')
619
620     # add another grantee by making the object public read
621     key.set_acl('public-read')
622
623     (ret, out) = rgwadmin_rest(admin_conn, ['policy', 'show'], {'bucket' : bucket.name, 'object' : key.key})
624     assert ret == 200
625
626     acl = key.get_xml_acl()
627     assert acl == out.strip('\n')
628
629     # TESTCASE 'rm-bucket', 'bucket', 'rm', 'bucket with objects', 'succeeds'
630     bucket = connection.create_bucket(bucket_name)
631     key_name = ['eight', 'nine', 'ten', 'eleven']
632     for i in range(4):
633         key = boto.s3.key.Key(bucket)
634         key.set_contents_from_string(key_name[i])
635
636     (ret, out) = rgwadmin_rest(admin_conn, ['bucket', 'rm'], {'bucket' : bucket_name, 'purge-objects' : True})
637     assert ret == 200
638
639     # TESTCASE 'caps-add', 'caps', 'add', 'add user cap', 'succeeds'
640     caps = 'usage=read'
641     (ret, out) = rgwadmin_rest(admin_conn, ['caps', 'add'], {'uid' :  user1, 'user-caps' : caps})
642     assert ret == 200
643     assert out[0]['perm'] == 'read'
644
645     # TESTCASE 'caps-rm', 'caps', 'rm', 'remove existing cap from user', 'succeeds'
646     (ret, out) = rgwadmin_rest(admin_conn, ['caps', 'rm'], {'uid' :  user1, 'user-caps' : caps})
647     assert ret == 200
648     assert not out
649
650     # TESTCASE 'rm-user','user','rm','existing user','fails, still has buckets'
651     bucket = connection.create_bucket(bucket_name)
652     key = boto.s3.key.Key(bucket)
653
654     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'rm'], {'uid' : user1})
655     assert ret == 409
656
657     # TESTCASE 'rm-user2', 'user', 'rm', user with data', 'succeeds'
658     bucket = connection.create_bucket(bucket_name)
659     key = boto.s3.key.Key(bucket)
660     key.set_contents_from_string('twelve')
661
662     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'rm'], {'uid' : user1, 'purge-data' : True})
663     assert ret == 200
664
665     # TESTCASE 'rm-user3','user','info','deleted user','fails'
666     (ret, out) = rgwadmin_rest(admin_conn, ['user', 'info'], {'uid' :  user1})
667     assert ret == 404
668