3 from __future__ import print_function
4 from __future__ import division
5 from builtins import str
6 from builtins import range
27 MY_DIRNAME = os.path.dirname(os.path.realpath(__file__))
28 if __name__ == '__main__' and os.path.exists(
29 os.path.join(MY_DIRNAME, '..', 'arvados', '__init__.py')):
30 # We're being launched to support another test suite.
31 # Add the Python SDK source to the library path.
32 sys.path.insert(1, os.path.dirname(MY_DIRNAME))
37 ARVADOS_DIR = os.path.realpath(os.path.join(MY_DIRNAME, '../../..'))
38 SERVICES_SRC_DIR = os.path.join(ARVADOS_DIR, 'services')
39 if 'GOPATH' in os.environ:
40 # Add all GOPATH bin dirs to PATH -- but insert them after the
41 # ruby gems bin dir, to ensure "bundle" runs the Ruby bundler
42 # command, not the golang.org/x/tools/cmd/bundle command.
43 gopaths = os.environ['GOPATH'].split(':')
44 addbins = [os.path.join(path, 'bin') for path in gopaths]
46 for path in os.environ['PATH'].split(':'):
48 if os.path.exists(os.path.join(path, 'bundle')):
52 os.environ['PATH'] = ':'.join(newbins)
54 TEST_TMPDIR = os.path.join(ARVADOS_DIR, 'tmp')
55 if not os.path.exists(TEST_TMPDIR):
60 _cached_db_config = {}
62 def find_server_pid(PID_PATH, wait=10):
66 while (not good_pid) and (now <= timeout):
69 with open(PID_PATH, 'r') as f:
70 server_pid = int(f.read())
71 good_pid = (os.kill(server_pid, 0) is None)
72 except EnvironmentError:
81 def kill_server_pid(pidfile, wait=10, passenger_root=False):
82 # Must re-import modules in order to work during atexit
93 # First try to shut down nicely
94 restore_cwd = os.getcwd()
95 os.chdir(passenger_root)
97 'bundle', 'exec', 'passenger', 'stop', '--pid-file', pidfile])
99 # Use up to half of the +wait+ period waiting for "passenger
100 # stop" to work. If the process hasn't exited by then, start
101 # sending TERM signals.
105 while now <= deadline and server_pid is None:
107 with open(pidfile, 'r') as f:
108 server_pid = int(f.read())
110 # No pidfile = nothing to kill.
112 except ValueError as error:
113 # Pidfile exists, but we can't parse it. Perhaps the
114 # server has created the file but hasn't written its PID
116 print("Parse error reading pidfile {}: {}".format(pidfile, error),
121 while now <= deadline:
123 exited, _ = os.waitpid(server_pid, os.WNOHANG)
125 _remove_pidfile(pidfile)
128 # already exited, or isn't our child process
132 os.kill(server_pid, signal.SIGTERM)
133 print("Sent SIGTERM to {} ({})".format(server_pid, pidfile),
135 except OSError as error:
136 if error.errno == errno.ESRCH:
137 # Thrown by os.getpgid() or os.kill() if the process
138 # does not exist, i.e., our work here is done.
139 _remove_pidfile(pidfile)
145 print("Server PID {} ({}) did not exit, giving up after {}s".
146 format(server_pid, pidfile, wait),
149 def _remove_pidfile(pidfile):
153 if os.path.lexists(pidfile):
156 def find_available_port():
157 """Return an IPv4 port number that is not in use right now.
159 We assume whoever needs to use the returned port is able to reuse
160 a recently used port without waiting for TIME_WAIT (see
161 SO_REUSEADDR / SO_REUSEPORT).
163 Some opportunity for races here, but it's better than choosing
164 something at random and not checking at all. If all of our servers
165 (hey Passenger) knew that listening on port 0 was a thing, the OS
166 would take care of the races, and this wouldn't be needed at all.
169 sock = socket.socket()
170 sock.bind(('0.0.0.0', 0))
171 port = sock.getsockname()[1]
175 def _wait_until_port_listens(port, timeout=10):
176 """Wait for a process to start listening on the given port.
178 If nothing listens on the port within the specified timeout (given
179 in seconds), print a warning on stderr before returning.
182 subprocess.check_output(['which', 'lsof'])
183 except subprocess.CalledProcessError:
184 print("WARNING: No `lsof` -- cannot wait for port to listen. "+
185 "Sleeping 0.5 and hoping for the best.",
189 deadline = time.time() + timeout
190 while time.time() < deadline:
192 subprocess.check_output(
193 ['lsof', '-t', '-i', 'tcp:'+str(port)])
194 except subprocess.CalledProcessError:
199 "WARNING: Nothing is listening on port {} (waited {} seconds).".
200 format(port, timeout),
203 def _fifo2stderr(label):
204 """Create a fifo, and copy it to stderr, prepending label to each line.
206 Return value is the path to the new FIFO.
208 +label+ should contain only alphanumerics: it is also used as part
209 of the FIFO filename.
211 fifo = os.path.join(TEST_TMPDIR, label+'.fifo')
214 except OSError as error:
215 if error.errno != errno.ENOENT:
217 os.mkfifo(fifo, 0o700)
219 ['stdbuf', '-i0', '-oL', '-eL', 'sed', '-e', 's/^/['+label+'] /', fifo],
223 def run(leave_running_atexit=False):
224 """Ensure an API server is running, and ARVADOS_API_* env vars have
225 admin credentials for it.
227 If ARVADOS_TEST_API_HOST is set, a parent process has started a
228 test server for us to use: we just need to reset() it using the
231 If a previous call to run() started a new server process, and it
232 is still running, we just need to reset() it to fixture state and
235 If neither of those options work out, we'll really start a new
240 # Delete cached discovery documents.
242 # This will clear cached docs that belong to other processes (like
243 # concurrent test suites) even if they're still running. They should
244 # be able to tolerate that.
245 for fn in glob.glob(os.path.join(
246 str(arvados.http_cache('discovery')),
247 '*,arvados,v1,rest,*')):
250 pid_file = _pidfile('api')
251 pid_file_ok = find_server_pid(pid_file, 0)
253 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
254 if existing_api_host and pid_file_ok:
255 if existing_api_host == my_api_host:
259 # Fall through to shutdown-and-start case.
262 # Server was provided by parent. Can't recover if it's
266 # Before trying to start up our own server, call stop() to avoid
267 # "Phusion Passenger Standalone is already running on PID 12345".
268 # (If we've gotten this far, ARVADOS_TEST_API_HOST isn't set, so
269 # we know the server is ours to kill.)
272 restore_cwd = os.getcwd()
273 api_src_dir = os.path.join(SERVICES_SRC_DIR, 'api')
274 os.chdir(api_src_dir)
276 # Either we haven't started a server of our own yet, or it has
277 # died, or we have lost our credentials, or something else is
278 # preventing us from calling reset(). Start a new one.
280 if not os.path.exists('tmp'):
283 if not os.path.exists('tmp/api'):
284 os.makedirs('tmp/api')
286 if not os.path.exists('tmp/logs'):
287 os.makedirs('tmp/logs')
289 if not os.path.exists('tmp/self-signed.pem'):
290 # We assume here that either passenger reports its listening
291 # address as https:/0.0.0.0:port/. If it reports "127.0.0.1"
292 # then the certificate won't match the host and reset() will
293 # fail certificate verification. If it reports "localhost",
294 # clients (notably Python SDK's websocket client) might
295 # resolve localhost as ::1 and then fail to connect.
296 subprocess.check_call([
297 'openssl', 'req', '-new', '-x509', '-nodes',
298 '-out', 'tmp/self-signed.pem',
299 '-keyout', 'tmp/self-signed.key',
301 '-subj', '/CN=0.0.0.0'],
304 # Install the git repository fixtures.
305 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
306 gittarball = os.path.join(SERVICES_SRC_DIR, 'api', 'test', 'test.git.tar')
307 if not os.path.isdir(gitdir):
309 subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
311 # The nginx proxy isn't listening here yet, but we need to choose
312 # the wss:// port now so we can write the API server config file.
313 wss_port = find_available_port()
314 _setport('wss', wss_port)
316 port = find_available_port()
317 env = os.environ.copy()
318 env['RAILS_ENV'] = 'test'
319 env['ARVADOS_TEST_WSS_PORT'] = str(wss_port)
320 if env.get('ARVADOS_TEST_EXPERIMENTAL_WS'):
321 env.pop('ARVADOS_WEBSOCKETS', None)
323 env['ARVADOS_WEBSOCKETS'] = 'yes'
324 env.pop('ARVADOS_TEST_API_HOST', None)
325 env.pop('ARVADOS_API_HOST', None)
326 env.pop('ARVADOS_API_HOST_INSECURE', None)
327 env.pop('ARVADOS_API_TOKEN', None)
328 start_msg = subprocess.check_output(
330 'passenger', 'start', '-d', '-p{}'.format(port),
331 '--pid-file', pid_file,
332 '--log-file', os.path.join(os.getcwd(), 'log/test.log'),
334 '--ssl-certificate', 'tmp/self-signed.pem',
335 '--ssl-certificate-key', 'tmp/self-signed.key'],
338 if not leave_running_atexit:
339 atexit.register(kill_server_pid, pid_file, passenger_root=api_src_dir)
341 match = re.search(r'Accessible via: https://(.*?)/', start_msg)
344 "Passenger did not report endpoint: {}".format(start_msg))
345 my_api_host = match.group(1)
346 os.environ['ARVADOS_API_HOST'] = my_api_host
348 # Make sure the server has written its pid file and started
349 # listening on its TCP port
350 find_server_pid(pid_file)
351 _wait_until_port_listens(port)
354 os.chdir(restore_cwd)
357 """Reset the test server to fixture state.
359 This resets the ARVADOS_TEST_API_HOST provided by a parent process
360 if any, otherwise the server started by run().
362 It also resets ARVADOS_* environment vars to point to the test
363 server with admin credentials.
365 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
366 token = auth_token('admin')
367 httpclient = httplib2.Http(ca_certs=os.path.join(
368 SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem'))
370 'https://{}/database/reset'.format(existing_api_host),
372 headers={'Authorization': 'OAuth2 {}'.format(token)})
373 os.environ['ARVADOS_API_HOST_INSECURE'] = 'true'
374 os.environ['ARVADOS_API_HOST'] = existing_api_host
375 os.environ['ARVADOS_API_TOKEN'] = token
377 def stop(force=False):
378 """Stop the API server, if one is running.
380 If force==False, kill it only if we started it ourselves. (This
381 supports the use case where a Python test suite calls run(), but
382 run() just uses the ARVADOS_TEST_API_HOST provided by the parent
383 process, and the test suite cleans up after itself by calling
384 stop(). In this case the test server provided by the parent
385 process should be left alone.)
387 If force==True, kill it even if we didn't start it
388 ourselves. (This supports the use case in __main__, where "run"
389 and "stop" happen in different processes.)
392 if force or my_api_host is not None:
393 kill_server_pid(_pidfile('api'))
397 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
400 port = find_available_port()
401 conf = os.path.join(TEST_TMPDIR, 'ws.yml')
402 with open(conf, 'w') as f:
415 """.format(os.environ['ARVADOS_API_HOST'],
417 ('info' if os.environ.get('ARVADOS_DEBUG', '') in ['','0'] else 'debug'),
419 _dbconfig('database'),
420 _dbconfig('username'),
421 _dbconfig('password')))
422 logf = open(_fifo2stderr('ws'), 'w')
423 ws = subprocess.Popen(
424 ["ws", "-config", conf],
425 stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
426 with open(_pidfile('ws'), 'w') as f:
428 _wait_until_port_listens(port)
433 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
435 kill_server_pid(_pidfile('ws'))
437 def _start_keep(n, keep_args):
438 keep0 = tempfile.mkdtemp()
439 port = find_available_port()
440 keep_cmd = ["keepstore",
441 "-volume={}".format(keep0),
442 "-listen=:{}".format(port),
443 "-pid="+_pidfile('keep{}'.format(n))]
445 for arg, val in keep_args.items():
446 keep_cmd.append("{}={}".format(arg, val))
448 logf = open(_fifo2stderr('keep{}'.format(n)), 'w')
449 kp0 = subprocess.Popen(
450 keep_cmd, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
452 with open(_pidfile('keep{}'.format(n)), 'w') as f:
453 f.write(str(kp0.pid))
455 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'w') as f:
458 _wait_until_port_listens(port)
462 def run_keep(blob_signing_key=None, enforce_permissions=False, num_servers=2):
463 stop_keep(num_servers)
466 if not blob_signing_key:
467 blob_signing_key = 'zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc'
468 with open(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"), "w") as f:
469 keep_args['-blob-signing-key-file'] = f.name
470 f.write(blob_signing_key)
471 keep_args['-enforce-permissions'] = str(enforce_permissions).lower()
472 with open(os.path.join(TEST_TMPDIR, "keep.data-manager-token-file"), "w") as f:
473 keep_args['-data-manager-token-file'] = f.name
474 f.write(auth_token('data_manager'))
475 keep_args['-never-delete'] = 'false'
479 host=os.environ['ARVADOS_API_HOST'],
480 token=os.environ['ARVADOS_API_TOKEN'],
483 for d in api.keep_services().list(filters=[['service_type','=','disk']]).execute()['items']:
484 api.keep_services().delete(uuid=d['uuid']).execute()
485 for d in api.keep_disks().list().execute()['items']:
486 api.keep_disks().delete(uuid=d['uuid']).execute()
488 for d in range(0, num_servers):
489 port = _start_keep(d, keep_args)
490 svc = api.keep_services().create(body={'keep_service': {
491 'uuid': 'zzzzz-bi6l4-keepdisk{:07d}'.format(d),
492 'service_host': 'localhost',
493 'service_port': port,
494 'service_type': 'disk',
495 'service_ssl_flag': False,
497 api.keep_disks().create(body={
498 'keep_disk': {'keep_service_uuid': svc['uuid'] }
501 # If keepproxy is running, send SIGHUP to make it discover the new
502 # keepstore services.
503 proxypidfile = _pidfile('keepproxy')
504 if os.path.exists(proxypidfile):
506 os.kill(int(open(proxypidfile).read()), signal.SIGHUP)
508 os.remove(proxypidfile)
511 kill_server_pid(_pidfile('keep{}'.format(n)))
512 if os.path.exists("{}/keep{}.volume".format(TEST_TMPDIR, n)):
513 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'r') as r:
514 shutil.rmtree(r.read(), True)
515 os.unlink("{}/keep{}.volume".format(TEST_TMPDIR, n))
516 if os.path.exists(os.path.join(TEST_TMPDIR, "keep.blob_signing_key")):
517 os.remove(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"))
519 def stop_keep(num_servers=2):
520 for n in range(0, num_servers):
523 def run_keep_proxy():
524 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
528 port = find_available_port()
529 env = os.environ.copy()
530 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
531 logf = open(_fifo2stderr('keepproxy'), 'w')
532 kp = subprocess.Popen(
534 '-pid='+_pidfile('keepproxy'),
535 '-listen=:{}'.format(port)],
536 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
540 host=os.environ['ARVADOS_API_HOST'],
541 token=auth_token('admin'),
543 for d in api.keep_services().list(
544 filters=[['service_type','=','proxy']]).execute()['items']:
545 api.keep_services().delete(uuid=d['uuid']).execute()
546 api.keep_services().create(body={'keep_service': {
547 'service_host': 'localhost',
548 'service_port': port,
549 'service_type': 'proxy',
550 'service_ssl_flag': False,
552 os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(port)
553 _setport('keepproxy', port)
554 _wait_until_port_listens(port)
556 def stop_keep_proxy():
557 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
559 kill_server_pid(_pidfile('keepproxy'))
561 def run_arv_git_httpd():
562 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
566 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
567 gitport = find_available_port()
568 env = os.environ.copy()
569 env.pop('ARVADOS_API_TOKEN', None)
570 logf = open(_fifo2stderr('arv-git-httpd'), 'w')
571 agh = subprocess.Popen(
573 '-repo-root='+gitdir+'/test',
574 '-address=:'+str(gitport)],
575 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
576 with open(_pidfile('arv-git-httpd'), 'w') as f:
577 f.write(str(agh.pid))
578 _setport('arv-git-httpd', gitport)
579 _wait_until_port_listens(gitport)
581 def stop_arv_git_httpd():
582 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
584 kill_server_pid(_pidfile('arv-git-httpd'))
587 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
591 keepwebport = find_available_port()
592 env = os.environ.copy()
593 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
594 logf = open(_fifo2stderr('keep-web'), 'w')
595 keepweb = subprocess.Popen(
598 '-attachment-only-host=download:'+str(keepwebport),
599 '-listen=:'+str(keepwebport)],
600 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
601 with open(_pidfile('keep-web'), 'w') as f:
602 f.write(str(keepweb.pid))
603 _setport('keep-web', keepwebport)
604 _wait_until_port_listens(keepwebport)
607 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
609 kill_server_pid(_pidfile('keep-web'))
612 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
616 nginxconf['KEEPWEBPORT'] = _getport('keep-web')
617 nginxconf['KEEPWEBDLSSLPORT'] = find_available_port()
618 nginxconf['KEEPWEBSSLPORT'] = find_available_port()
619 nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
620 nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
621 nginxconf['GITPORT'] = _getport('arv-git-httpd')
622 nginxconf['GITSSLPORT'] = find_available_port()
623 nginxconf['WSPORT'] = _getport('ws')
624 nginxconf['WSSPORT'] = _getport('wss')
625 nginxconf['SSLCERT'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem')
626 nginxconf['SSLKEY'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.key')
627 nginxconf['ACCESSLOG'] = _fifo2stderr('nginx_access_log')
629 conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
630 conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
631 with open(conffile, 'w') as f:
634 lambda match: str(nginxconf.get(match.group(1))),
635 open(conftemplatefile).read()))
637 env = os.environ.copy()
638 env['PATH'] = env['PATH']+':/sbin:/usr/sbin:/usr/local/sbin'
640 nginx = subprocess.Popen(
642 '-g', 'error_log stderr info;',
643 '-g', 'pid '+_pidfile('nginx')+';',
645 env=env, stdin=open('/dev/null'), stdout=sys.stderr)
646 _setport('keep-web-dl-ssl', nginxconf['KEEPWEBDLSSLPORT'])
647 _setport('keep-web-ssl', nginxconf['KEEPWEBSSLPORT'])
648 _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
649 _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
652 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
654 kill_server_pid(_pidfile('nginx'))
656 def _pidfile(program):
657 return os.path.join(TEST_TMPDIR, program + '.pid')
659 def _portfile(program):
660 return os.path.join(TEST_TMPDIR, program + '.port')
662 def _setport(program, port):
663 with open(_portfile(program), 'w') as f:
666 # Returns 9 if program is not up.
667 def _getport(program):
669 return int(open(_portfile(program)).read())
674 global _cached_db_config
675 if not _cached_db_config:
676 _cached_db_config = yaml.load(open(os.path.join(
677 SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
678 return _cached_db_config['test'][key]
681 global _cached_config
683 return _cached_config[key]
684 def _load(f, required=True):
685 fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
686 if not required and not os.path.exists(fullpath):
688 return yaml.load(fullpath)
689 cdefault = _load('application.default.yml')
690 csite = _load('application.yml', required=False)
692 for section in [cdefault.get('common',{}), cdefault.get('test',{}),
693 csite.get('common',{}), csite.get('test',{})]:
694 _cached_config.update(section)
695 return _cached_config[key]
698 '''load a fixture yaml file'''
699 with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
703 trim_index = yaml_file.index("# Test Helper trims the rest of the file")
704 yaml_file = yaml_file[0:trim_index]
707 return yaml.load(yaml_file)
709 def auth_token(token_name):
710 return fixture("api_client_authorizations")[token_name]["api_token"]
712 def authorize_with(token_name):
713 '''token_name is the symbolic name of the token from the api_client_authorizations fixture'''
714 arvados.config.settings()["ARVADOS_API_TOKEN"] = auth_token(token_name)
715 arvados.config.settings()["ARVADOS_API_HOST"] = os.environ.get("ARVADOS_API_HOST")
716 arvados.config.settings()["ARVADOS_API_HOST_INSECURE"] = "true"
718 class TestCaseWithServers(unittest.TestCase):
719 """TestCase to start and stop supporting Arvados servers.
721 Define any of MAIN_SERVER, KEEP_SERVER, and/or KEEP_PROXY_SERVER
722 class variables as a dictionary of keyword arguments. If you do,
723 setUpClass will start the corresponding servers by passing these
724 keyword arguments to the run, run_keep, and/or run_keep_server
725 functions, respectively. It will also set Arvados environment
726 variables to point to these servers appropriately. If you don't
727 run a Keep or Keep proxy server, setUpClass will set up a
728 temporary directory for Keep local storage, and set it as
731 tearDownClass will stop any servers started, and restore the
732 original environment.
737 KEEP_PROXY_SERVER = None
738 KEEP_WEB_SERVER = None
741 def _restore_dict(src, dest):
742 for key in list(dest.keys()):
749 cls._orig_environ = os.environ.copy()
750 cls._orig_config = arvados.config.settings().copy()
751 cls._cleanup_funcs = []
752 os.environ.pop('ARVADOS_KEEP_SERVICES', None)
753 os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
754 for server_kwargs, start_func, stop_func in (
755 (cls.MAIN_SERVER, run, reset),
756 (cls.WS_SERVER, run_ws, stop_ws),
757 (cls.KEEP_SERVER, run_keep, stop_keep),
758 (cls.KEEP_PROXY_SERVER, run_keep_proxy, stop_keep_proxy),
759 (cls.KEEP_WEB_SERVER, run_keep_web, stop_keep_web)):
760 if server_kwargs is not None:
761 start_func(**server_kwargs)
762 cls._cleanup_funcs.append(stop_func)
763 if (cls.KEEP_SERVER is None) and (cls.KEEP_PROXY_SERVER is None):
764 cls.local_store = tempfile.mkdtemp()
765 os.environ['KEEP_LOCAL_STORE'] = cls.local_store
766 cls._cleanup_funcs.append(
767 lambda: shutil.rmtree(cls.local_store, ignore_errors=True))
769 os.environ.pop('KEEP_LOCAL_STORE', None)
770 arvados.config.initialize()
773 def tearDownClass(cls):
774 for clean_func in cls._cleanup_funcs:
776 cls._restore_dict(cls._orig_environ, os.environ)
777 cls._restore_dict(cls._orig_config, arvados.config.settings())
780 if __name__ == "__main__":
783 'start_ws', 'stop_ws',
784 'start_keep', 'stop_keep',
785 'start_keep_proxy', 'stop_keep_proxy',
786 'start_keep-web', 'stop_keep-web',
787 'start_arv-git-httpd', 'stop_arv-git-httpd',
788 'start_nginx', 'stop_nginx',
790 parser = argparse.ArgumentParser()
791 parser.add_argument('action', type=str, help="one of {}".format(actions))
792 parser.add_argument('--auth', type=str, metavar='FIXTURE_NAME', help='Print authorization info for given api_client_authorizations fixture')
793 parser.add_argument('--num-keep-servers', metavar='int', type=int, default=2, help="Number of keep servers desired")
794 parser.add_argument('--keep-enforce-permissions', action="store_true", help="Enforce keep permissions")
796 args = parser.parse_args()
798 if args.action not in actions:
799 print("Unrecognized action '{}'. Actions are: {}.".
800 format(args.action, actions),
803 if args.action == 'start':
804 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
805 run(leave_running_atexit=True)
806 host = os.environ['ARVADOS_API_HOST']
807 if args.auth is not None:
808 token = auth_token(args.auth)
809 print("export ARVADOS_API_TOKEN={}".format(pipes.quote(token)))
810 print("export ARVADOS_API_HOST={}".format(pipes.quote(host)))
811 print("export ARVADOS_API_HOST_INSECURE=true")
814 elif args.action == 'stop':
815 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
816 elif args.action == 'start_ws':
818 elif args.action == 'stop_ws':
820 elif args.action == 'start_keep':
821 run_keep(enforce_permissions=args.keep_enforce_permissions, num_servers=args.num_keep_servers)
822 elif args.action == 'stop_keep':
823 stop_keep(num_servers=args.num_keep_servers)
824 elif args.action == 'start_keep_proxy':
826 elif args.action == 'stop_keep_proxy':
828 elif args.action == 'start_arv-git-httpd':
830 elif args.action == 'stop_arv-git-httpd':
832 elif args.action == 'start_keep-web':
834 elif args.action == 'stop_keep-web':
836 elif args.action == 'start_nginx':
838 elif args.action == 'stop_nginx':
841 raise Exception("action recognized but not implemented!?")