]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
rgw: Add a test for multi-tenancy 8592/head
authorPete Zaitcev <zaitcev@kotori.zaitcev.us>
Fri, 15 Apr 2016 22:46:56 +0000 (16:46 -0600)
committerPete Zaitcev <zaitcev@kotori.zaitcev.us>
Fri, 15 Apr 2016 22:46:56 +0000 (16:46 -0600)
This is a very rudimentary test for now. For one thing, it
only creates a tenantized user, but does not even try to run
the radosgw and access it with Boto. And it already has several
XXX tags. But baby steps.

Two areas of exising code had to be fixed up.

 - We forgot to patch an argument through in RGWcluster.rgw_admin()

 - We must not process the arguments of a command through eval(1)
   in test-rgw-call.sh. This causes a double-eval with the function
   x() in test-rgw-common.sh, and as a result arguments with spaces
   or dollars cannot be used. There is no way to escape or quote.
   But we need the dollar for the tenant!

Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
src/test/rgw/test-rgw-call.sh
src/test/rgw/test-rgw-common.sh
src/test/rgw/test_multen.py [new file with mode: 0644]
src/test/rgw/test_multi.py

index 72ce106ede1352f63ae9a02faacacd5c66d61e41..39a3f8fd0016bd18ce7b89cc885ed92db6645aa4 100755 (executable)
@@ -3,4 +3,7 @@
 . "`dirname $0`/test-rgw-common.sh"
 . "`dirname $0`/test-rgw-meta-sync.sh"
 
-eval "$@"
+# Do not use eval here. We have eval in test-rgw-common.sh:x(), so adding
+# one here creates a double-eval situation. Passing arguments with spaces
+# becomes impossible when double-eval strips escaping and quotes.
+$@
index 47d02bcf04412d587e5a742f4ff5d5dfaaf8154b..a61653daf43ef73408360d74867e503ac11b8dc0 100644 (file)
@@ -48,7 +48,7 @@ END
 
 
 x() {
-  # echo "x " "$@"
+  # echo "x " "$@" >&2
   eval "$@"
 }
 
diff --git a/src/test/rgw/test_multen.py b/src/test/rgw/test_multen.py
new file mode 100644 (file)
index 0000000..a8b0d17
--- /dev/null
@@ -0,0 +1,182 @@
+# Test of mult-tenancy
+
+import json
+import sys
+
+# XXX once we're done, break out the common code into a library module
+import test_multi as t
+
+class TestException(Exception):
+    pass
+
+#
+# Create a traditional user, S3-only, global (empty) tenant
+#
+def test2(cluster):
+    uid = "tester2"
+    display_name = "'Test User 2'"
+    access_key = "tester2KEY"
+    s3_secret = "test3pass"
+    cmd = t.build_cmd('--uid', uid,
+                    '--display-name', display_name,
+                    '--access-key', access_key,
+                    '--secret', s3_secret,
+                    "user create")
+    out, ret = cluster.rgw_admin(cmd, check_retcode=False)
+    if ret != 0:
+        raise TestException("failed command: user create --uid %s" % uid)
+
+    try:
+        outj = json.loads(out)
+    except ValueError:
+        raise TestException("invalid json after: user create --uid %s" % uid)
+    if not isinstance(outj, dict):
+        raise TestException("bad json after: user create --uid %s" % uid)
+    if outj['user_id'] != uid:
+        raise TestException(
+            "command: user create --uid %s, returned user_id %s" %
+            (uid, outj['user_id']))
+
+#
+# Create a tenantized user with --tenant foo
+#
+def test3(cluster):
+    tid = "testx3"
+    uid = "tester3"
+    display_name = "Test_User_3"
+    access_key = "tester3KEY"
+    s3_secret = "test3pass"
+    cmd = t.build_cmd(
+        '--tenant', tid,
+        '--uid', uid,
+        '--display-name', display_name,
+        '--access-key', access_key,
+        '--secret', s3_secret,
+        "user create")
+    out, ret = cluster.rgw_admin(cmd, check_retcode=False)
+    if ret != 0:
+        raise TestException("failed command: user create --uid %s" % uid)
+
+    try:
+        outj = json.loads(out)
+    except ValueError:
+        raise TestException("invalid json after: user create --uid %s" % uid)
+    if not isinstance(outj, dict):
+        raise TestException("bad json after: user create --uid %s" % uid)
+    tid_uid = "%s$%s" % (tid, uid)
+    if outj['user_id'] != tid_uid:
+        raise TestException(
+            "command: user create --uid %s, returned user_id %s" %
+            (tid_uid, outj['user_id']))
+
+#
+# Create a tenantized user with a subuser
+#
+# N.B. The aim of this test is not just to create a subuser, but to create
+# the key with a separate command, which does not use --tenant, but extracts
+# the tenant from the subuser. No idea why we allow this. There was some kind
+# of old script that did this.
+#
+def test4(cluster):
+    tid = "testx4"
+    uid = "tester4"
+    subid = "test4"
+
+    display_name = "Test_User_4"
+    cmd = t.build_cmd(
+        '--tenant', tid,
+        '--uid', uid,
+        '--display-name', display_name,
+        '--subuser', '%s:%s' % (uid, subid),
+        '--key-type', 'swift',
+        '--access', 'full',
+        "user create")
+    out, ret = cluster.rgw_admin(cmd, check_retcode=False)
+    if ret != 0:
+        raise TestException("failed command: user create --uid %s" % uid)
+
+    try:
+        outj = json.loads(out)
+    except ValueError:
+        raise TestException("invalid json after: user create --uid %s" % uid)
+    if not isinstance(outj, dict):
+        raise TestException("bad json after: user create --uid %s" % uid)
+    tid_uid = "%s$%s" % (tid, uid)
+    if outj['user_id'] != tid_uid:
+        raise TestException(
+            "command: user create --uid %s, returned user_id %s" %
+            (tid_uid, outj['user_id']))
+    # XXX maybe add some more checking here for keys and such
+
+    # Note that this tests a way to identify a fully-qualified subuser
+    # without --tenant and --uid. This is a historic use that we support.
+    swift_secret = "test3pass"
+    cmd = t.build_cmd(
+        '--subuser', "'%s$%s:%s'" % (tid, uid, subid),
+        '--key-type', 'swift',
+        '--secret', swift_secret,
+        "key create")
+    out, ret = cluster.rgw_admin(cmd, check_retcode=False)
+    if ret != 0:
+        raise TestException("failed command: key create --uid %s" % uid)
+
+    try:
+        outj = json.loads(out)
+    except ValueError:
+        raise TestException("invalid json after: key create --uid %s" % uid)
+    if not isinstance(outj, dict):
+        raise TestException("bad json after: key create --uid %s" % uid)
+    tid_uid = "%s$%s" % (tid, uid)
+    if outj['user_id'] != tid_uid:
+        raise TestException(
+            "command: key create --uid %s, returned user_id %s" %
+            (tid_uid, outj['user_id']))
+    skj = outj['swift_keys'][0]
+    if skj['secret_key'] != swift_secret: 
+        raise TestException(
+            "command: key create --uid %s, returned swift key %s" %
+            (tid_uid, skj['secret_key']))
+
+# XXX this parse_args boolean makes no sense. we should pass argv[] instead,
+#     possibly empty. (copied from test_multi, correct it there too)
+def init(parse_args):
+
+    #argv = []
+    #if parse_args:
+    #    argv = sys.argv[1:]
+    #args = parser.parse_args(argv)
+
+    #rgw_multi = RGWMulti(int(args.num_zones))
+    #rgw_multi.setup(not args.no_bootstrap)
+
+    # __init__():
+    port = 8001
+    clnum = 1  # number of clusters
+    clid = 1   # 1-based
+    cluster = t.RGWCluster(clid, port)
+
+    # setup():
+    cluster.start()
+
+    # The cluster is always reset at this point, so we don't need to list
+    # users or delete pre-existing users.
+
+    try:
+        test2(cluster)
+        test3(cluster)
+        test4(cluster)
+    except TestException as e:
+        cluster.stop()
+        sys.stderr.write("FAIL\n")
+        sys.stderr.write("%s\n" % str(e))
+        return 1
+
+    # teardown():
+    cluster.stop()
+    return 0
+
+def setup_module():
+    return init(False)
+
+if __name__ == "__main__":
+    sys.exit(init(True))
index 92460d74f05128b002fe4c13cc81422a557faf43..88626851a659c9146dd0f9d8adfe05d5606e18df 100644 (file)
@@ -124,7 +124,7 @@ class RGWCluster:
         mstop(self.cluster_id, 'radosgw')
 
     def rgw_admin(self, cmd, check_retcode = True):
-        (s, retcode) = bash(tpath('test-rgw-call.sh', 'call_rgw_admin', self.cluster_num, cmd))
+        (s, retcode) = bash(tpath('test-rgw-call.sh', 'call_rgw_admin', self.cluster_num, cmd), check_retcode)
         return (s, retcode)
 
     def rgw_admin_ro(self, cmd, check_retcode = True):