Merge branch 'master' into 3153-auto-setup-user
[arvados.git] / sdk / python / tests / run_test_server.py
index dc95d8a9a5ac3f0781ed4aec9fa10d713f66479b..0173718debf5b2eee05c06dcc6cc8c7f4b79a036 100644 (file)
@@ -8,6 +8,7 @@ import subprocess
 import sys
 import tempfile
 import time
+import unittest
 import yaml
 
 MY_DIRNAME = os.path.dirname(os.path.realpath(__file__))
@@ -20,10 +21,13 @@ if __name__ == '__main__' and os.path.exists(
 import arvados.api
 import arvados.config
 
-ARV_API_SERVER_DIR = '../../../services/api'
-KEEP_SERVER_DIR = '../../../services/keep'
+SERVICES_SRC_DIR = os.path.join(MY_DIRNAME, '../../../services')
 SERVER_PID_PATH = 'tmp/pids/webrick-test.pid'
 WEBSOCKETS_SERVER_PID_PATH = 'tmp/pids/passenger-test.pid'
+if 'GOPATH' in os.environ:
+    gopaths = os.environ['GOPATH'].split(':')
+    gobins = [os.path.join(path, 'bin') for path in gopaths]
+    os.environ['PATH'] = ':'.join(gobins) + ':' + os.environ['PATH']
 
 def find_server_pid(PID_PATH, wait=10):
     now = time.time()
@@ -64,7 +68,7 @@ def kill_server_pid(PID_PATH, wait=10):
 
 def run(websockets=False, reuse_server=False):
     cwd = os.getcwd()
-    os.chdir(os.path.join(MY_DIRNAME, ARV_API_SERVER_DIR))
+    os.chdir(os.path.join(SERVICES_SRC_DIR, 'api'))
 
     if websockets:
         pid_file = WEBSOCKETS_SERVER_PID_PATH
@@ -116,7 +120,7 @@ def run(websockets=False, reuse_server=False):
 
 def stop():
     cwd = os.getcwd()
-    os.chdir(os.path.join(MY_DIRNAME, ARV_API_SERVER_DIR))
+    os.chdir(os.path.join(SERVICES_SRC_DIR, 'api'))
 
     kill_server_pid(WEBSOCKETS_SERVER_PID_PATH, 0)
     kill_server_pid(SERVER_PID_PATH, 0)
@@ -135,41 +139,32 @@ def stop():
 
 def _start_keep(n, keep_args):
     keep0 = tempfile.mkdtemp()
-    keep_cmd = ["bin/keep",
+    keep_cmd = ["keepstore",
                 "-volumes={}".format(keep0),
                 "-listen=:{}".format(25107+n),
-                "-pid={}".format("tmp/keep{}.pid".format(n))]
+                "-pid={}".format("tests/tmp/keep{}.pid".format(n))]
 
     for arg, val in keep_args.iteritems():
         keep_cmd.append("{}={}".format(arg, val))
 
     kp0 = subprocess.Popen(keep_cmd)
-    with open("tmp/keep{}.pid".format(n), 'w') as f:
+    with open("tests/tmp/keep{}.pid".format(n), 'w') as f:
         f.write(str(kp0.pid))
 
-    with open("tmp/keep{}.volume".format(n), 'w') as f:
+    with open("tests/tmp/keep{}.volume".format(n), 'w') as f:
         f.write(keep0)
 
 def run_keep(blob_signing_key=None, enforce_permissions=False):
     stop_keep()
 
-    cwd = os.getcwd()
-    os.chdir(os.path.join(MY_DIRNAME, KEEP_SERVER_DIR))
-    if os.environ.get('GOPATH') == None:
-        os.environ["GOPATH"] = os.getcwd()
-    else:
-        os.environ["GOPATH"] = os.getcwd() + ":" + os.environ["GOPATH"]
-
-    subprocess.call(["./go.sh", "install", "keep"])
-
-    if not os.path.exists("tmp"):
-        os.mkdir("tmp")
+    if not os.path.exists("tests/tmp"):
+        os.mkdir("tests/tmp")
 
     keep_args = {}
     if blob_signing_key:
-        with open("tmp/keep.blob_signing_key", "w") as f:
+        with open("tests/tmp/keep.blob_signing_key", "w") as f:
             f.write(blob_signing_key)
-        keep_args['--permission-key-file'] = 'tmp/keep.blob_signing_key'
+        keep_args['--permission-key-file'] = 'tests/tmp/keep.blob_signing_key'
     if enforce_permissions:
         keep_args['--enforce-permissions'] = 'true'
 
@@ -191,64 +186,45 @@ def run_keep(blob_signing_key=None, enforce_permissions=False):
     api.keep_disks().create(body={"keep_disk": {"keep_service_uuid": s1["uuid"] } }).execute()
     api.keep_disks().create(body={"keep_disk": {"keep_service_uuid": s2["uuid"] } }).execute()
 
-    os.chdir(cwd)
-
 def _stop_keep(n):
-    kill_server_pid("tmp/keep{}.pid".format(n), 0)
-    if os.path.exists("tmp/keep{}.volume".format(n)):
-        with open("tmp/keep{}.volume".format(n), 'r') as r:
+    kill_server_pid("tests/tmp/keep{}.pid".format(n), 0)
+    if os.path.exists("tests/tmp/keep{}.volume".format(n)):
+        with open("tests/tmp/keep{}.volume".format(n), 'r') as r:
             shutil.rmtree(r.read(), True)
-        os.unlink("tmp/keep{}.volume".format(n))
-    if os.path.exists("tmp/keep.blob_signing_key"):
-        os.remove("tmp/keep.blob_signing_key")
+        os.unlink("tests/tmp/keep{}.volume".format(n))
+    if os.path.exists("tests/tmp/keep.blob_signing_key"):
+        os.remove("tests/tmp/keep.blob_signing_key")
 
 def stop_keep():
-    cwd = os.getcwd()
-    os.chdir(os.path.join(MY_DIRNAME, KEEP_SERVER_DIR))
-
     _stop_keep(0)
     _stop_keep(1)
 
-    os.chdir(cwd)
-
 def run_keep_proxy(auth):
     stop_keep_proxy()
 
-    cwd = os.getcwd()
-    os.chdir(os.path.join(MY_DIRNAME, KEEP_SERVER_DIR))
-    if os.environ.get('GOPATH') == None:
-        os.environ["GOPATH"] = os.getcwd()
-    else:
-        os.environ["GOPATH"] = os.getcwd() + ":" + os.environ["GOPATH"]
-
-    subprocess.call(["./go.sh", "install", "arvados.org/keepproxy"])
-
-    if not os.path.exists("tmp"):
-        os.mkdir("tmp")
+    if not os.path.exists("tests/tmp"):
+        os.mkdir("tests/tmp")
 
     os.environ["ARVADOS_API_HOST"] = "127.0.0.1:3001"
     os.environ["ARVADOS_API_HOST_INSECURE"] = "true"
     os.environ["ARVADOS_API_TOKEN"] = fixture("api_client_authorizations")[auth]["api_token"]
 
-    kp0 = subprocess.Popen(["bin/keepproxy", "-pid=tmp/keepproxy.pid", "-listen=:{}".format(25101)])
+    kp0 = subprocess.Popen(["keepproxy",
+                            "-pid=tests/tmp/keepproxy.pid",
+                            "-listen=:{}".format(25101)])
 
     authorize_with("admin")
     api = arvados.api('v1', cache=False)
     api.keep_services().create(body={"keep_service": {"service_host": "localhost",  "service_port": 25101, "service_type": "proxy"} }).execute()
 
-    arvados.config.settings()["ARVADOS_KEEP_PROXY"] = "http://localhost:25101"
-
-    os.chdir(cwd)
+    os.environ["ARVADOS_KEEP_PROXY"] = "http://localhost:25101"
 
 def stop_keep_proxy():
-    cwd = os.getcwd()
-    os.chdir(os.path.join(MY_DIRNAME, KEEP_SERVER_DIR))
-    kill_server_pid("tmp/keepproxy.pid", 0)
-    os.chdir(cwd)
+    kill_server_pid("tests/tmp/keepproxy.pid", 0)
 
 def fixture(fix):
     '''load a fixture yaml file'''
-    with open(os.path.join(MY_DIRNAME, ARV_API_SERVER_DIR, "test", "fixtures",
+    with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
                            fix + ".yml")) as f:
         return yaml.load(f.read())
 
@@ -258,6 +234,65 @@ def authorize_with(token):
     arvados.config.settings()["ARVADOS_API_HOST"] = os.environ.get("ARVADOS_API_HOST")
     arvados.config.settings()["ARVADOS_API_HOST_INSECURE"] = "true"
 
+class TestCaseWithServers(unittest.TestCase):
+    """TestCase to start and stop supporting Arvados servers.
+
+    Define any of MAIN_SERVER, KEEP_SERVER, and/or KEEP_PROXY_SERVER
+    class variables as a dictionary of keyword arguments.  If you do,
+    setUpClass will start the corresponding servers by passing these
+    keyword arguments to the run, run_keep, and/or run_keep_server
+    functions, respectively.  It will also set Arvados environment
+    variables to point to these servers appropriately.  If you don't
+    run a Keep or Keep proxy server, setUpClass will set up a
+    temporary directory for Keep local storage, and set it as
+    KEEP_LOCAL_STORE.
+
+    tearDownClass will stop any servers started, and restore the
+    original environment.
+    """
+    MAIN_SERVER = None
+    KEEP_SERVER = None
+    KEEP_PROXY_SERVER = None
+
+    @staticmethod
+    def _restore_dict(src, dest):
+        for key in dest.keys():
+            if key not in src:
+                del dest[key]
+        dest.update(src)
+
+    @classmethod
+    def setUpClass(cls):
+        cls._orig_environ = os.environ.copy()
+        cls._orig_config = arvados.config.settings().copy()
+        cls._cleanup_funcs = []
+        for server_kwargs, start_func, stop_func in (
+              (cls.MAIN_SERVER, run, stop),
+              (cls.KEEP_SERVER, run_keep, stop_keep),
+              (cls.KEEP_PROXY_SERVER, run_keep_proxy, stop_keep_proxy)):
+            if server_kwargs is not None:
+                start_func(**server_kwargs)
+                cls._cleanup_funcs.append(stop_func)
+        os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
+        if cls.KEEP_PROXY_SERVER is None:
+            os.environ.pop('ARVADOS_KEEP_PROXY', None)
+        if (cls.KEEP_SERVER is None) and (cls.KEEP_PROXY_SERVER is None):
+            cls.local_store = tempfile.mkdtemp()
+            os.environ['KEEP_LOCAL_STORE'] = cls.local_store
+            cls._cleanup_funcs.append(
+                lambda: shutil.rmtree(cls.local_store, ignore_errors=True))
+        else:
+            os.environ.pop('KEEP_LOCAL_STORE', None)
+        arvados.config.initialize()
+
+    @classmethod
+    def tearDownClass(cls):
+        for clean_func in cls._cleanup_funcs:
+            clean_func()
+        cls._restore_dict(cls._orig_environ, os.environ)
+        cls._restore_dict(cls._orig_config, arvados.config.settings())
+
+
 if __name__ == "__main__":
     parser = argparse.ArgumentParser()
     parser.add_argument('action', type=str, help='''one of "start", "stop", "start_keep", "stop_keep"''')