3 from __future__ import print_function
24 MY_DIRNAME = os.path.dirname(os.path.realpath(__file__))
25 if __name__ == '__main__' and os.path.exists(
26 os.path.join(MY_DIRNAME, '..', 'arvados', '__init__.py')):
27 # We're being launched to support another test suite.
28 # Add the Python SDK source to the library path.
29 sys.path.insert(1, os.path.dirname(MY_DIRNAME))
34 ARVADOS_DIR = os.path.realpath(os.path.join(MY_DIRNAME, '../../..'))
35 SERVICES_SRC_DIR = os.path.join(ARVADOS_DIR, 'services')
36 if 'GOPATH' in os.environ:
37 # Add all GOPATH bin dirs to PATH -- but insert them after the
38 # ruby gems bin dir, to ensure "bundle" runs the Ruby bundler
39 # command, not the golang.org/x/tools/cmd/bundle command.
40 gopaths = os.environ['GOPATH'].split(':')
41 addbins = [os.path.join(path, 'bin') for path in gopaths]
43 for path in os.environ['PATH'].split(':'):
45 if os.path.exists(os.path.join(path, 'bundle')):
49 os.environ['PATH'] = ':'.join(newbins)
51 TEST_TMPDIR = os.path.join(ARVADOS_DIR, 'tmp')
52 if not os.path.exists(TEST_TMPDIR):
57 _cached_db_config = {}
59 def find_server_pid(PID_PATH, wait=10):
63 while (not good_pid) and (now <= timeout):
66 with open(PID_PATH, 'r') as f:
67 server_pid = int(f.read())
68 good_pid = (os.kill(server_pid, 0) is None)
69 except EnvironmentError:
78 def kill_server_pid(pidfile, wait=10, passenger_root=False):
79 # Must re-import modules in order to work during atexit
90 # First try to shut down nicely
91 restore_cwd = os.getcwd()
92 os.chdir(passenger_root)
94 'bundle', 'exec', 'passenger', 'stop', '--pid-file', pidfile])
96 # Use up to half of the +wait+ period waiting for "passenger
97 # stop" to work. If the process hasn't exited by then, start
98 # sending TERM signals.
102 while now <= deadline and server_pid is None:
104 with open(pidfile, 'r') as f:
105 server_pid = int(f.read())
107 # No pidfile = nothing to kill.
109 except ValueError as error:
110 # Pidfile exists, but we can't parse it. Perhaps the
111 # server has created the file but hasn't written its PID
113 print("Parse error reading pidfile {}: {}".format(pidfile, error),
118 while now <= deadline:
120 exited, _ = os.waitpid(server_pid, os.WNOHANG)
122 _remove_pidfile(pidfile)
125 # already exited, or isn't our child process
129 os.kill(server_pid, signal.SIGTERM)
130 print("Sent SIGTERM to {} ({})".format(server_pid, pidfile),
132 except OSError as error:
133 if error.errno == errno.ESRCH:
134 # Thrown by os.getpgid() or os.kill() if the process
135 # does not exist, i.e., our work here is done.
136 _remove_pidfile(pidfile)
142 print("Server PID {} ({}) did not exit, giving up after {}s".
143 format(server_pid, pidfile, wait),
146 def _remove_pidfile(pidfile):
150 if os.path.lexists(pidfile):
153 def find_available_port():
154 """Return an IPv4 port number that is not in use right now.
156 We assume whoever needs to use the returned port is able to reuse
157 a recently used port without waiting for TIME_WAIT (see
158 SO_REUSEADDR / SO_REUSEPORT).
160 Some opportunity for races here, but it's better than choosing
161 something at random and not checking at all. If all of our servers
162 (hey Passenger) knew that listening on port 0 was a thing, the OS
163 would take care of the races, and this wouldn't be needed at all.
166 sock = socket.socket()
167 sock.bind(('0.0.0.0', 0))
168 port = sock.getsockname()[1]
172 def _wait_until_port_listens(port, timeout=10):
173 """Wait for a process to start listening on the given port.
175 If nothing listens on the port within the specified timeout (given
176 in seconds), print a warning on stderr before returning.
179 subprocess.check_output(['which', 'lsof'])
180 except subprocess.CalledProcessError:
181 print("WARNING: No `lsof` -- cannot wait for port to listen. "+
182 "Sleeping 0.5 and hoping for the best.",
186 deadline = time.time() + timeout
187 while time.time() < deadline:
189 subprocess.check_output(
190 ['lsof', '-t', '-i', 'tcp:'+str(port)])
191 except subprocess.CalledProcessError:
196 "WARNING: Nothing is listening on port {} (waited {} seconds).".
197 format(port, timeout),
200 def _fifo2stderr(label):
201 """Create a fifo, and copy it to stderr, prepending label to each line.
203 Return value is the path to the new FIFO.
205 +label+ should contain only alphanumerics: it is also used as part
206 of the FIFO filename.
208 fifo = os.path.join(TEST_TMPDIR, label+'.fifo')
211 except OSError as error:
212 if error.errno != errno.ENOENT:
214 os.mkfifo(fifo, 0700)
216 ['stdbuf', '-i0', '-oL', '-eL', 'sed', '-e', 's/^/['+label+'] /', fifo],
220 def run(leave_running_atexit=False):
221 """Ensure an API server is running, and ARVADOS_API_* env vars have
222 admin credentials for it.
224 If ARVADOS_TEST_API_HOST is set, a parent process has started a
225 test server for us to use: we just need to reset() it using the
228 If a previous call to run() started a new server process, and it
229 is still running, we just need to reset() it to fixture state and
232 If neither of those options work out, we'll really start a new
237 # Delete cached discovery documents.
239 # This will clear cached docs that belong to other processes (like
240 # concurrent test suites) even if they're still running. They should
241 # be able to tolerate that.
242 for fn in glob.glob(os.path.join(
243 str(arvados.http_cache('discovery')),
244 '*,arvados,v1,rest,*')):
247 pid_file = _pidfile('api')
248 pid_file_ok = find_server_pid(pid_file, 0)
250 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
251 if existing_api_host and pid_file_ok:
252 if existing_api_host == my_api_host:
256 # Fall through to shutdown-and-start case.
259 # Server was provided by parent. Can't recover if it's
263 # Before trying to start up our own server, call stop() to avoid
264 # "Phusion Passenger Standalone is already running on PID 12345".
265 # (If we've gotten this far, ARVADOS_TEST_API_HOST isn't set, so
266 # we know the server is ours to kill.)
269 restore_cwd = os.getcwd()
270 api_src_dir = os.path.join(SERVICES_SRC_DIR, 'api')
271 os.chdir(api_src_dir)
273 # Either we haven't started a server of our own yet, or it has
274 # died, or we have lost our credentials, or something else is
275 # preventing us from calling reset(). Start a new one.
277 if not os.path.exists('tmp'):
280 if not os.path.exists('tmp/api'):
281 os.makedirs('tmp/api')
283 if not os.path.exists('tmp/logs'):
284 os.makedirs('tmp/logs')
286 if not os.path.exists('tmp/self-signed.pem'):
287 # We assume here that either passenger reports its listening
288 # address as https:/0.0.0.0:port/. If it reports "127.0.0.1"
289 # then the certificate won't match the host and reset() will
290 # fail certificate verification. If it reports "localhost",
291 # clients (notably Python SDK's websocket client) might
292 # resolve localhost as ::1 and then fail to connect.
293 subprocess.check_call([
294 'openssl', 'req', '-new', '-x509', '-nodes',
295 '-out', 'tmp/self-signed.pem',
296 '-keyout', 'tmp/self-signed.key',
298 '-subj', '/CN=0.0.0.0'],
301 # Install the git repository fixtures.
302 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
303 gittarball = os.path.join(SERVICES_SRC_DIR, 'api', 'test', 'test.git.tar')
304 if not os.path.isdir(gitdir):
306 subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
308 # The nginx proxy isn't listening here yet, but we need to choose
309 # the wss:// port now so we can write the API server config file.
310 wss_port = find_available_port()
311 _setport('wss', wss_port)
313 port = find_available_port()
314 env = os.environ.copy()
315 env['RAILS_ENV'] = 'test'
316 env['ARVADOS_TEST_WSS_PORT'] = str(wss_port)
317 env.pop('ARVADOS_WEBSOCKETS', None)
318 env.pop('ARVADOS_TEST_API_HOST', None)
319 env.pop('ARVADOS_API_HOST', None)
320 env.pop('ARVADOS_API_HOST_INSECURE', None)
321 env.pop('ARVADOS_API_TOKEN', None)
322 start_msg = subprocess.check_output(
324 'passenger', 'start', '-d', '-p{}'.format(port),
325 '--pid-file', pid_file,
326 '--log-file', os.path.join(os.getcwd(), 'log/test.log'),
328 '--ssl-certificate', 'tmp/self-signed.pem',
329 '--ssl-certificate-key', 'tmp/self-signed.key'],
332 if not leave_running_atexit:
333 atexit.register(kill_server_pid, pid_file, passenger_root=api_src_dir)
335 match = re.search(r'Accessible via: https://(.*?)/', start_msg)
338 "Passenger did not report endpoint: {}".format(start_msg))
339 my_api_host = match.group(1)
340 os.environ['ARVADOS_API_HOST'] = my_api_host
342 # Make sure the server has written its pid file and started
343 # listening on its TCP port
344 find_server_pid(pid_file)
345 _wait_until_port_listens(port)
348 os.chdir(restore_cwd)
351 """Reset the test server to fixture state.
353 This resets the ARVADOS_TEST_API_HOST provided by a parent process
354 if any, otherwise the server started by run().
356 It also resets ARVADOS_* environment vars to point to the test
357 server with admin credentials.
359 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
360 token = auth_token('admin')
361 httpclient = httplib2.Http(ca_certs=os.path.join(
362 SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem'))
364 'https://{}/database/reset'.format(existing_api_host),
366 headers={'Authorization': 'OAuth2 {}'.format(token)})
367 os.environ['ARVADOS_API_HOST_INSECURE'] = 'true'
368 os.environ['ARVADOS_API_HOST'] = existing_api_host
369 os.environ['ARVADOS_API_TOKEN'] = token
371 def stop(force=False):
372 """Stop the API server, if one is running.
374 If force==False, kill it only if we started it ourselves. (This
375 supports the use case where a Python test suite calls run(), but
376 run() just uses the ARVADOS_TEST_API_HOST provided by the parent
377 process, and the test suite cleans up after itself by calling
378 stop(). In this case the test server provided by the parent
379 process should be left alone.)
381 If force==True, kill it even if we didn't start it
382 ourselves. (This supports the use case in __main__, where "run"
383 and "stop" happen in different processes.)
386 if force or my_api_host is not None:
387 kill_server_pid(_pidfile('api'))
391 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
394 port = find_available_port()
395 conf = os.path.join(TEST_TMPDIR, 'ws.yml')
396 with open(conf, 'w') as f:
409 """.format(os.environ['ARVADOS_API_HOST'],
411 ('info' if os.environ.get('ARVADOS_DEBUG', '') in ['','0'] else 'debug'),
413 _dbconfig('database'),
414 _dbconfig('username'),
415 _dbconfig('password')))
416 logf = open(_fifo2stderr('ws'), 'w')
417 ws = subprocess.Popen(
418 ["ws", "-config", conf],
419 stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
420 with open(_pidfile('ws'), 'w') as f:
422 _wait_until_port_listens(port)
427 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
429 kill_server_pid(_pidfile('ws'))
431 def _start_keep(n, keep_args):
432 keep0 = tempfile.mkdtemp()
433 port = find_available_port()
434 keep_cmd = ["keepstore",
435 "-volume={}".format(keep0),
436 "-listen=:{}".format(port),
437 "-pid="+_pidfile('keep{}'.format(n))]
439 for arg, val in keep_args.iteritems():
440 keep_cmd.append("{}={}".format(arg, val))
442 logf = open(_fifo2stderr('keep{}'.format(n)), 'w')
443 kp0 = subprocess.Popen(
444 keep_cmd, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
446 with open(_pidfile('keep{}'.format(n)), 'w') as f:
447 f.write(str(kp0.pid))
449 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'w') as f:
452 _wait_until_port_listens(port)
456 def run_keep(blob_signing_key=None, enforce_permissions=False, num_servers=2):
457 stop_keep(num_servers)
460 if not blob_signing_key:
461 blob_signing_key = 'zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc'
462 with open(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"), "w") as f:
463 keep_args['-blob-signing-key-file'] = f.name
464 f.write(blob_signing_key)
465 keep_args['-enforce-permissions'] = str(enforce_permissions).lower()
466 with open(os.path.join(TEST_TMPDIR, "keep.data-manager-token-file"), "w") as f:
467 keep_args['-data-manager-token-file'] = f.name
468 f.write(auth_token('data_manager'))
469 keep_args['-never-delete'] = 'false'
473 host=os.environ['ARVADOS_API_HOST'],
474 token=os.environ['ARVADOS_API_TOKEN'],
477 for d in api.keep_services().list(filters=[['service_type','=','disk']]).execute()['items']:
478 api.keep_services().delete(uuid=d['uuid']).execute()
479 for d in api.keep_disks().list().execute()['items']:
480 api.keep_disks().delete(uuid=d['uuid']).execute()
482 for d in range(0, num_servers):
483 port = _start_keep(d, keep_args)
484 svc = api.keep_services().create(body={'keep_service': {
485 'uuid': 'zzzzz-bi6l4-keepdisk{:07d}'.format(d),
486 'service_host': 'localhost',
487 'service_port': port,
488 'service_type': 'disk',
489 'service_ssl_flag': False,
491 api.keep_disks().create(body={
492 'keep_disk': {'keep_service_uuid': svc['uuid'] }
495 # If keepproxy is running, send SIGHUP to make it discover the new
496 # keepstore services.
497 proxypidfile = _pidfile('keepproxy')
498 if os.path.exists(proxypidfile):
500 os.kill(int(open(proxypidfile).read()), signal.SIGHUP)
502 os.remove(proxypidfile)
505 kill_server_pid(_pidfile('keep{}'.format(n)))
506 if os.path.exists("{}/keep{}.volume".format(TEST_TMPDIR, n)):
507 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'r') as r:
508 shutil.rmtree(r.read(), True)
509 os.unlink("{}/keep{}.volume".format(TEST_TMPDIR, n))
510 if os.path.exists(os.path.join(TEST_TMPDIR, "keep.blob_signing_key")):
511 os.remove(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"))
513 def stop_keep(num_servers=2):
514 for n in range(0, num_servers):
517 def run_keep_proxy():
518 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
522 port = find_available_port()
523 env = os.environ.copy()
524 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
525 logf = open(_fifo2stderr('keepproxy'), 'w')
526 kp = subprocess.Popen(
528 '-pid='+_pidfile('keepproxy'),
529 '-listen=:{}'.format(port)],
530 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
534 host=os.environ['ARVADOS_API_HOST'],
535 token=auth_token('admin'),
537 for d in api.keep_services().list(
538 filters=[['service_type','=','proxy']]).execute()['items']:
539 api.keep_services().delete(uuid=d['uuid']).execute()
540 api.keep_services().create(body={'keep_service': {
541 'service_host': 'localhost',
542 'service_port': port,
543 'service_type': 'proxy',
544 'service_ssl_flag': False,
546 os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(port)
547 _setport('keepproxy', port)
548 _wait_until_port_listens(port)
550 def stop_keep_proxy():
551 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
553 kill_server_pid(_pidfile('keepproxy'))
555 def run_arv_git_httpd():
556 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
560 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
561 gitport = find_available_port()
562 env = os.environ.copy()
563 env.pop('ARVADOS_API_TOKEN', None)
564 logf = open(_fifo2stderr('arv-git-httpd'), 'w')
565 agh = subprocess.Popen(
567 '-repo-root='+gitdir+'/test',
568 '-address=:'+str(gitport)],
569 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
570 with open(_pidfile('arv-git-httpd'), 'w') as f:
571 f.write(str(agh.pid))
572 _setport('arv-git-httpd', gitport)
573 _wait_until_port_listens(gitport)
575 def stop_arv_git_httpd():
576 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
578 kill_server_pid(_pidfile('arv-git-httpd'))
581 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
585 keepwebport = find_available_port()
586 env = os.environ.copy()
587 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
588 logf = open(_fifo2stderr('keep-web'), 'w')
589 keepweb = subprocess.Popen(
592 '-attachment-only-host=download:'+str(keepwebport),
593 '-listen=:'+str(keepwebport)],
594 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
595 with open(_pidfile('keep-web'), 'w') as f:
596 f.write(str(keepweb.pid))
597 _setport('keep-web', keepwebport)
598 _wait_until_port_listens(keepwebport)
601 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
603 kill_server_pid(_pidfile('keep-web'))
606 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
610 nginxconf['KEEPWEBPORT'] = _getport('keep-web')
611 nginxconf['KEEPWEBDLSSLPORT'] = find_available_port()
612 nginxconf['KEEPWEBSSLPORT'] = find_available_port()
613 nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
614 nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
615 nginxconf['GITPORT'] = _getport('arv-git-httpd')
616 nginxconf['GITSSLPORT'] = find_available_port()
617 nginxconf['WSPORT'] = _getport('ws')
618 nginxconf['WSSPORT'] = _getport('wss')
619 nginxconf['SSLCERT'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem')
620 nginxconf['SSLKEY'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.key')
621 nginxconf['ACCESSLOG'] = _fifo2stderr('nginx_access_log')
623 conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
624 conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
625 with open(conffile, 'w') as f:
628 lambda match: str(nginxconf.get(match.group(1))),
629 open(conftemplatefile).read()))
631 env = os.environ.copy()
632 env['PATH'] = env['PATH']+':/sbin:/usr/sbin:/usr/local/sbin'
634 nginx = subprocess.Popen(
636 '-g', 'error_log stderr info;',
637 '-g', 'pid '+_pidfile('nginx')+';',
639 env=env, stdin=open('/dev/null'), stdout=sys.stderr)
640 _setport('keep-web-dl-ssl', nginxconf['KEEPWEBDLSSLPORT'])
641 _setport('keep-web-ssl', nginxconf['KEEPWEBSSLPORT'])
642 _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
643 _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
646 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
648 kill_server_pid(_pidfile('nginx'))
650 def _pidfile(program):
651 return os.path.join(TEST_TMPDIR, program + '.pid')
653 def _portfile(program):
654 return os.path.join(TEST_TMPDIR, program + '.port')
656 def _setport(program, port):
657 with open(_portfile(program), 'w') as f:
660 # Returns 9 if program is not up.
661 def _getport(program):
663 return int(open(_portfile(program)).read())
668 global _cached_db_config
669 if not _cached_db_config:
670 _cached_db_config = yaml.load(open(os.path.join(
671 SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
672 return _cached_db_config['test'][key]
675 global _cached_config
677 return _cached_config[key]
678 def _load(f, required=True):
679 fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
680 if not required and not os.path.exists(fullpath):
682 return yaml.load(fullpath)
683 cdefault = _load('application.default.yml')
684 csite = _load('application.yml', required=False)
686 for section in [cdefault.get('common',{}), cdefault.get('test',{}),
687 csite.get('common',{}), csite.get('test',{})]:
688 _cached_config.update(section)
689 return _cached_config[key]
692 '''load a fixture yaml file'''
693 with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
697 trim_index = yaml_file.index("# Test Helper trims the rest of the file")
698 yaml_file = yaml_file[0:trim_index]
701 return yaml.load(yaml_file)
703 def auth_token(token_name):
704 return fixture("api_client_authorizations")[token_name]["api_token"]
706 def authorize_with(token_name):
707 '''token_name is the symbolic name of the token from the api_client_authorizations fixture'''
708 arvados.config.settings()["ARVADOS_API_TOKEN"] = auth_token(token_name)
709 arvados.config.settings()["ARVADOS_API_HOST"] = os.environ.get("ARVADOS_API_HOST")
710 arvados.config.settings()["ARVADOS_API_HOST_INSECURE"] = "true"
712 class TestCaseWithServers(unittest.TestCase):
713 """TestCase to start and stop supporting Arvados servers.
715 Define any of MAIN_SERVER, KEEP_SERVER, and/or KEEP_PROXY_SERVER
716 class variables as a dictionary of keyword arguments. If you do,
717 setUpClass will start the corresponding servers by passing these
718 keyword arguments to the run, run_keep, and/or run_keep_server
719 functions, respectively. It will also set Arvados environment
720 variables to point to these servers appropriately. If you don't
721 run a Keep or Keep proxy server, setUpClass will set up a
722 temporary directory for Keep local storage, and set it as
725 tearDownClass will stop any servers started, and restore the
726 original environment.
731 KEEP_PROXY_SERVER = None
732 KEEP_WEB_SERVER = None
735 def _restore_dict(src, dest):
736 for key in dest.keys():
743 cls._orig_environ = os.environ.copy()
744 cls._orig_config = arvados.config.settings().copy()
745 cls._cleanup_funcs = []
746 os.environ.pop('ARVADOS_KEEP_SERVICES', None)
747 os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
748 for server_kwargs, start_func, stop_func in (
749 (cls.MAIN_SERVER, run, reset),
750 (cls.WS_SERVER, run_ws, stop_ws),
751 (cls.KEEP_SERVER, run_keep, stop_keep),
752 (cls.KEEP_PROXY_SERVER, run_keep_proxy, stop_keep_proxy),
753 (cls.KEEP_WEB_SERVER, run_keep_web, stop_keep_web)):
754 if server_kwargs is not None:
755 start_func(**server_kwargs)
756 cls._cleanup_funcs.append(stop_func)
757 if (cls.KEEP_SERVER is None) and (cls.KEEP_PROXY_SERVER is None):
758 cls.local_store = tempfile.mkdtemp()
759 os.environ['KEEP_LOCAL_STORE'] = cls.local_store
760 cls._cleanup_funcs.append(
761 lambda: shutil.rmtree(cls.local_store, ignore_errors=True))
763 os.environ.pop('KEEP_LOCAL_STORE', None)
764 arvados.config.initialize()
767 def tearDownClass(cls):
768 for clean_func in cls._cleanup_funcs:
770 cls._restore_dict(cls._orig_environ, os.environ)
771 cls._restore_dict(cls._orig_config, arvados.config.settings())
774 if __name__ == "__main__":
777 'start_ws', 'stop_ws',
778 'start_keep', 'stop_keep',
779 'start_keep_proxy', 'stop_keep_proxy',
780 'start_keep-web', 'stop_keep-web',
781 'start_arv-git-httpd', 'stop_arv-git-httpd',
782 'start_nginx', 'stop_nginx',
784 parser = argparse.ArgumentParser()
785 parser.add_argument('action', type=str, help="one of {}".format(actions))
786 parser.add_argument('--auth', type=str, metavar='FIXTURE_NAME', help='Print authorization info for given api_client_authorizations fixture')
787 parser.add_argument('--num-keep-servers', metavar='int', type=int, default=2, help="Number of keep servers desired")
788 parser.add_argument('--keep-enforce-permissions', action="store_true", help="Enforce keep permissions")
790 args = parser.parse_args()
792 if args.action not in actions:
793 print("Unrecognized action '{}'. Actions are: {}.".
794 format(args.action, actions),
797 if args.action == 'start':
798 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
799 run(leave_running_atexit=True)
800 host = os.environ['ARVADOS_API_HOST']
801 if args.auth is not None:
802 token = auth_token(args.auth)
803 print("export ARVADOS_API_TOKEN={}".format(pipes.quote(token)))
804 print("export ARVADOS_API_HOST={}".format(pipes.quote(host)))
805 print("export ARVADOS_API_HOST_INSECURE=true")
808 elif args.action == 'stop':
809 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
810 elif args.action == 'start_ws':
812 elif args.action == 'stop_ws':
814 elif args.action == 'start_keep':
815 run_keep(enforce_permissions=args.keep_enforce_permissions, num_servers=args.num_keep_servers)
816 elif args.action == 'stop_keep':
817 stop_keep(num_servers=args.num_keep_servers)
818 elif args.action == 'start_keep_proxy':
820 elif args.action == 'stop_keep_proxy':
822 elif args.action == 'start_arv-git-httpd':
824 elif args.action == 'stop_arv-git-httpd':
826 elif args.action == 'start_keep-web':
828 elif args.action == 'stop_keep-web':
830 elif args.action == 'start_nginx':
832 elif args.action == 'stop_nginx':
835 raise Exception("action recognized but not implemented!?")