1 from __future__ import print_function
2 from __future__ import division
3 from builtins import str
4 from builtins import range
25 MY_DIRNAME = os.path.dirname(os.path.realpath(__file__))
26 if __name__ == '__main__' and os.path.exists(
27 os.path.join(MY_DIRNAME, '..', 'arvados', '__init__.py')):
28 # We're being launched to support another test suite.
29 # Add the Python SDK source to the library path.
30 sys.path.insert(1, os.path.dirname(MY_DIRNAME))
35 ARVADOS_DIR = os.path.realpath(os.path.join(MY_DIRNAME, '../../..'))
36 SERVICES_SRC_DIR = os.path.join(ARVADOS_DIR, 'services')
37 if 'GOPATH' in os.environ:
38 # Add all GOPATH bin dirs to PATH -- but insert them after the
39 # ruby gems bin dir, to ensure "bundle" runs the Ruby bundler
40 # command, not the golang.org/x/tools/cmd/bundle command.
41 gopaths = os.environ['GOPATH'].split(':')
42 addbins = [os.path.join(path, 'bin') for path in gopaths]
44 for path in os.environ['PATH'].split(':'):
46 if os.path.exists(os.path.join(path, 'bundle')):
50 os.environ['PATH'] = ':'.join(newbins)
52 TEST_TMPDIR = os.path.join(ARVADOS_DIR, 'tmp')
53 if not os.path.exists(TEST_TMPDIR):
58 _cached_db_config = {}
60 def find_server_pid(PID_PATH, wait=10):
64 while (not good_pid) and (now <= timeout):
67 with open(PID_PATH, 'r') as f:
68 server_pid = int(f.read())
69 good_pid = (os.kill(server_pid, 0) is None)
70 except EnvironmentError:
79 def kill_server_pid(pidfile, wait=10, passenger_root=False):
80 # Must re-import modules in order to work during atexit
91 # First try to shut down nicely
92 restore_cwd = os.getcwd()
93 os.chdir(passenger_root)
95 'bundle', 'exec', 'passenger', 'stop', '--pid-file', pidfile])
97 # Use up to half of the +wait+ period waiting for "passenger
98 # stop" to work. If the process hasn't exited by then, start
99 # sending TERM signals.
103 while now <= deadline and server_pid is None:
105 with open(pidfile, 'r') as f:
106 server_pid = int(f.read())
108 # No pidfile = nothing to kill.
110 except ValueError as error:
111 # Pidfile exists, but we can't parse it. Perhaps the
112 # server has created the file but hasn't written its PID
114 print("Parse error reading pidfile {}: {}".format(pidfile, error),
119 while now <= deadline:
121 exited, _ = os.waitpid(server_pid, os.WNOHANG)
123 _remove_pidfile(pidfile)
126 # already exited, or isn't our child process
130 os.kill(server_pid, signal.SIGTERM)
131 print("Sent SIGTERM to {} ({})".format(server_pid, pidfile),
133 except OSError as error:
134 if error.errno == errno.ESRCH:
135 # Thrown by os.getpgid() or os.kill() if the process
136 # does not exist, i.e., our work here is done.
137 _remove_pidfile(pidfile)
143 print("Server PID {} ({}) did not exit, giving up after {}s".
144 format(server_pid, pidfile, wait),
147 def _remove_pidfile(pidfile):
151 if os.path.lexists(pidfile):
154 def find_available_port():
155 """Return an IPv4 port number that is not in use right now.
157 We assume whoever needs to use the returned port is able to reuse
158 a recently used port without waiting for TIME_WAIT (see
159 SO_REUSEADDR / SO_REUSEPORT).
161 Some opportunity for races here, but it's better than choosing
162 something at random and not checking at all. If all of our servers
163 (hey Passenger) knew that listening on port 0 was a thing, the OS
164 would take care of the races, and this wouldn't be needed at all.
167 sock = socket.socket()
168 sock.bind(('0.0.0.0', 0))
169 port = sock.getsockname()[1]
173 def _wait_until_port_listens(port, timeout=10):
174 """Wait for a process to start listening on the given port.
176 If nothing listens on the port within the specified timeout (given
177 in seconds), print a warning on stderr before returning.
180 subprocess.check_output(['which', 'lsof'])
181 except subprocess.CalledProcessError:
182 print("WARNING: No `lsof` -- cannot wait for port to listen. "+
183 "Sleeping 0.5 and hoping for the best.",
187 deadline = time.time() + timeout
188 while time.time() < deadline:
190 subprocess.check_output(
191 ['lsof', '-t', '-i', 'tcp:'+str(port)])
192 except subprocess.CalledProcessError:
197 "WARNING: Nothing is listening on port {} (waited {} seconds).".
198 format(port, timeout),
201 def _fifo2stderr(label):
202 """Create a fifo, and copy it to stderr, prepending label to each line.
204 Return value is the path to the new FIFO.
206 +label+ should contain only alphanumerics: it is also used as part
207 of the FIFO filename.
209 fifo = os.path.join(TEST_TMPDIR, label+'.fifo')
212 except OSError as error:
213 if error.errno != errno.ENOENT:
215 os.mkfifo(fifo, 0o700)
217 ['stdbuf', '-i0', '-oL', '-eL', 'sed', '-e', 's/^/['+label+'] /', fifo],
221 def run(leave_running_atexit=False):
222 """Ensure an API server is running, and ARVADOS_API_* env vars have
223 admin credentials for it.
225 If ARVADOS_TEST_API_HOST is set, a parent process has started a
226 test server for us to use: we just need to reset() it using the
229 If a previous call to run() started a new server process, and it
230 is still running, we just need to reset() it to fixture state and
233 If neither of those options work out, we'll really start a new
238 # Delete cached discovery documents.
240 # This will clear cached docs that belong to other processes (like
241 # concurrent test suites) even if they're still running. They should
242 # be able to tolerate that.
243 for fn in glob.glob(os.path.join(
244 str(arvados.http_cache('discovery')),
245 '*,arvados,v1,rest,*')):
248 pid_file = _pidfile('api')
249 pid_file_ok = find_server_pid(pid_file, 0)
251 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
252 if existing_api_host and pid_file_ok:
253 if existing_api_host == my_api_host:
257 # Fall through to shutdown-and-start case.
260 # Server was provided by parent. Can't recover if it's
264 # Before trying to start up our own server, call stop() to avoid
265 # "Phusion Passenger Standalone is already running on PID 12345".
266 # (If we've gotten this far, ARVADOS_TEST_API_HOST isn't set, so
267 # we know the server is ours to kill.)
270 restore_cwd = os.getcwd()
271 api_src_dir = os.path.join(SERVICES_SRC_DIR, 'api')
272 os.chdir(api_src_dir)
274 # Either we haven't started a server of our own yet, or it has
275 # died, or we have lost our credentials, or something else is
276 # preventing us from calling reset(). Start a new one.
278 if not os.path.exists('tmp'):
281 if not os.path.exists('tmp/api'):
282 os.makedirs('tmp/api')
284 if not os.path.exists('tmp/logs'):
285 os.makedirs('tmp/logs')
287 if not os.path.exists('tmp/self-signed.pem'):
288 # We assume here that either passenger reports its listening
289 # address as https:/0.0.0.0:port/. If it reports "127.0.0.1"
290 # then the certificate won't match the host and reset() will
291 # fail certificate verification. If it reports "localhost",
292 # clients (notably Python SDK's websocket client) might
293 # resolve localhost as ::1 and then fail to connect.
294 subprocess.check_call([
295 'openssl', 'req', '-new', '-x509', '-nodes',
296 '-out', 'tmp/self-signed.pem',
297 '-keyout', 'tmp/self-signed.key',
299 '-subj', '/CN=0.0.0.0'],
302 # Install the git repository fixtures.
303 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
304 gittarball = os.path.join(SERVICES_SRC_DIR, 'api', 'test', 'test.git.tar')
305 if not os.path.isdir(gitdir):
307 subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
309 # The nginx proxy isn't listening here yet, but we need to choose
310 # the wss:// port now so we can write the API server config file.
311 wss_port = find_available_port()
312 _setport('wss', wss_port)
314 port = find_available_port()
315 env = os.environ.copy()
316 env['RAILS_ENV'] = 'test'
317 env['ARVADOS_TEST_WSS_PORT'] = str(wss_port)
318 env.pop('ARVADOS_WEBSOCKETS', None)
319 env.pop('ARVADOS_TEST_API_HOST', None)
320 env.pop('ARVADOS_API_HOST', None)
321 env.pop('ARVADOS_API_HOST_INSECURE', None)
322 env.pop('ARVADOS_API_TOKEN', None)
323 start_msg = subprocess.check_output(
325 'passenger', 'start', '-d', '-p{}'.format(port),
326 '--pid-file', pid_file,
327 '--log-file', os.path.join(os.getcwd(), 'log/test.log'),
329 '--ssl-certificate', 'tmp/self-signed.pem',
330 '--ssl-certificate-key', 'tmp/self-signed.key'],
333 if not leave_running_atexit:
334 atexit.register(kill_server_pid, pid_file, passenger_root=api_src_dir)
336 match = re.search(r'Accessible via: https://(.*?)/', start_msg)
339 "Passenger did not report endpoint: {}".format(start_msg))
340 my_api_host = match.group(1)
341 os.environ['ARVADOS_API_HOST'] = my_api_host
343 # Make sure the server has written its pid file and started
344 # listening on its TCP port
345 find_server_pid(pid_file)
346 _wait_until_port_listens(port)
349 os.chdir(restore_cwd)
352 """Reset the test server to fixture state.
354 This resets the ARVADOS_TEST_API_HOST provided by a parent process
355 if any, otherwise the server started by run().
357 It also resets ARVADOS_* environment vars to point to the test
358 server with admin credentials.
360 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
361 token = auth_token('admin')
362 httpclient = httplib2.Http(ca_certs=os.path.join(
363 SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem'))
365 'https://{}/database/reset'.format(existing_api_host),
367 headers={'Authorization': 'OAuth2 {}'.format(token)})
368 os.environ['ARVADOS_API_HOST_INSECURE'] = 'true'
369 os.environ['ARVADOS_API_HOST'] = existing_api_host
370 os.environ['ARVADOS_API_TOKEN'] = token
372 def stop(force=False):
373 """Stop the API server, if one is running.
375 If force==False, kill it only if we started it ourselves. (This
376 supports the use case where a Python test suite calls run(), but
377 run() just uses the ARVADOS_TEST_API_HOST provided by the parent
378 process, and the test suite cleans up after itself by calling
379 stop(). In this case the test server provided by the parent
380 process should be left alone.)
382 If force==True, kill it even if we didn't start it
383 ourselves. (This supports the use case in __main__, where "run"
384 and "stop" happen in different processes.)
387 if force or my_api_host is not None:
388 kill_server_pid(_pidfile('api'))
392 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
395 port = find_available_port()
396 conf = os.path.join(TEST_TMPDIR, 'ws.yml')
397 with open(conf, 'w') as f:
410 """.format(os.environ['ARVADOS_API_HOST'],
412 ('info' if os.environ.get('ARVADOS_DEBUG', '') in ['','0'] else 'debug'),
414 _dbconfig('database'),
415 _dbconfig('username'),
416 _dbconfig('password')))
417 logf = open(_fifo2stderr('ws'), 'w')
418 ws = subprocess.Popen(
419 ["ws", "-config", conf],
420 stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
421 with open(_pidfile('ws'), 'w') as f:
423 _wait_until_port_listens(port)
428 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
430 kill_server_pid(_pidfile('ws'))
432 def _start_keep(n, keep_args):
433 keep0 = tempfile.mkdtemp()
434 port = find_available_port()
435 keep_cmd = ["keepstore",
436 "-volume={}".format(keep0),
437 "-listen=:{}".format(port),
438 "-pid="+_pidfile('keep{}'.format(n))]
440 for arg, val in keep_args.items():
441 keep_cmd.append("{}={}".format(arg, val))
443 logf = open(_fifo2stderr('keep{}'.format(n)), 'w')
444 kp0 = subprocess.Popen(
445 keep_cmd, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
447 with open(_pidfile('keep{}'.format(n)), 'w') as f:
448 f.write(str(kp0.pid))
450 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'w') as f:
453 _wait_until_port_listens(port)
457 def run_keep(blob_signing_key=None, enforce_permissions=False, num_servers=2):
458 stop_keep(num_servers)
461 if not blob_signing_key:
462 blob_signing_key = 'zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc'
463 with open(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"), "w") as f:
464 keep_args['-blob-signing-key-file'] = f.name
465 f.write(blob_signing_key)
466 keep_args['-enforce-permissions'] = str(enforce_permissions).lower()
467 with open(os.path.join(TEST_TMPDIR, "keep.data-manager-token-file"), "w") as f:
468 keep_args['-data-manager-token-file'] = f.name
469 f.write(auth_token('data_manager'))
470 keep_args['-never-delete'] = 'false'
474 host=os.environ['ARVADOS_API_HOST'],
475 token=os.environ['ARVADOS_API_TOKEN'],
478 for d in api.keep_services().list(filters=[['service_type','=','disk']]).execute()['items']:
479 api.keep_services().delete(uuid=d['uuid']).execute()
480 for d in api.keep_disks().list().execute()['items']:
481 api.keep_disks().delete(uuid=d['uuid']).execute()
483 for d in range(0, num_servers):
484 port = _start_keep(d, keep_args)
485 svc = api.keep_services().create(body={'keep_service': {
486 'uuid': 'zzzzz-bi6l4-keepdisk{:07d}'.format(d),
487 'service_host': 'localhost',
488 'service_port': port,
489 'service_type': 'disk',
490 'service_ssl_flag': False,
492 api.keep_disks().create(body={
493 'keep_disk': {'keep_service_uuid': svc['uuid'] }
496 # If keepproxy is running, send SIGHUP to make it discover the new
497 # keepstore services.
498 proxypidfile = _pidfile('keepproxy')
499 if os.path.exists(proxypidfile):
501 os.kill(int(open(proxypidfile).read()), signal.SIGHUP)
503 os.remove(proxypidfile)
506 kill_server_pid(_pidfile('keep{}'.format(n)))
507 if os.path.exists("{}/keep{}.volume".format(TEST_TMPDIR, n)):
508 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'r') as r:
509 shutil.rmtree(r.read(), True)
510 os.unlink("{}/keep{}.volume".format(TEST_TMPDIR, n))
511 if os.path.exists(os.path.join(TEST_TMPDIR, "keep.blob_signing_key")):
512 os.remove(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"))
514 def stop_keep(num_servers=2):
515 for n in range(0, num_servers):
518 def run_keep_proxy():
519 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
523 port = find_available_port()
524 env = os.environ.copy()
525 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
526 logf = open(_fifo2stderr('keepproxy'), 'w')
527 kp = subprocess.Popen(
529 '-pid='+_pidfile('keepproxy'),
530 '-listen=:{}'.format(port)],
531 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
535 host=os.environ['ARVADOS_API_HOST'],
536 token=auth_token('admin'),
538 for d in api.keep_services().list(
539 filters=[['service_type','=','proxy']]).execute()['items']:
540 api.keep_services().delete(uuid=d['uuid']).execute()
541 api.keep_services().create(body={'keep_service': {
542 'service_host': 'localhost',
543 'service_port': port,
544 'service_type': 'proxy',
545 'service_ssl_flag': False,
547 os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(port)
548 _setport('keepproxy', port)
549 _wait_until_port_listens(port)
551 def stop_keep_proxy():
552 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
554 kill_server_pid(_pidfile('keepproxy'))
556 def run_arv_git_httpd():
557 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
561 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
562 gitport = find_available_port()
563 env = os.environ.copy()
564 env.pop('ARVADOS_API_TOKEN', None)
565 logf = open(_fifo2stderr('arv-git-httpd'), 'w')
566 agh = subprocess.Popen(
568 '-repo-root='+gitdir+'/test',
569 '-address=:'+str(gitport)],
570 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
571 with open(_pidfile('arv-git-httpd'), 'w') as f:
572 f.write(str(agh.pid))
573 _setport('arv-git-httpd', gitport)
574 _wait_until_port_listens(gitport)
576 def stop_arv_git_httpd():
577 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
579 kill_server_pid(_pidfile('arv-git-httpd'))
582 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
586 keepwebport = find_available_port()
587 env = os.environ.copy()
588 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
589 logf = open(_fifo2stderr('keep-web'), 'w')
590 keepweb = subprocess.Popen(
593 '-attachment-only-host=download:'+str(keepwebport),
594 '-listen=:'+str(keepwebport)],
595 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
596 with open(_pidfile('keep-web'), 'w') as f:
597 f.write(str(keepweb.pid))
598 _setport('keep-web', keepwebport)
599 _wait_until_port_listens(keepwebport)
602 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
604 kill_server_pid(_pidfile('keep-web'))
607 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
611 nginxconf['KEEPWEBPORT'] = _getport('keep-web')
612 nginxconf['KEEPWEBDLSSLPORT'] = find_available_port()
613 nginxconf['KEEPWEBSSLPORT'] = find_available_port()
614 nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
615 nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
616 nginxconf['GITPORT'] = _getport('arv-git-httpd')
617 nginxconf['GITSSLPORT'] = find_available_port()
618 nginxconf['WSPORT'] = _getport('ws')
619 nginxconf['WSSPORT'] = _getport('wss')
620 nginxconf['SSLCERT'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem')
621 nginxconf['SSLKEY'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.key')
622 nginxconf['ACCESSLOG'] = _fifo2stderr('nginx_access_log')
624 conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
625 conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
626 with open(conffile, 'w') as f:
629 lambda match: str(nginxconf.get(match.group(1))),
630 open(conftemplatefile).read()))
632 env = os.environ.copy()
633 env['PATH'] = env['PATH']+':/sbin:/usr/sbin:/usr/local/sbin'
635 nginx = subprocess.Popen(
637 '-g', 'error_log stderr info;',
638 '-g', 'pid '+_pidfile('nginx')+';',
640 env=env, stdin=open('/dev/null'), stdout=sys.stderr)
641 _setport('keep-web-dl-ssl', nginxconf['KEEPWEBDLSSLPORT'])
642 _setport('keep-web-ssl', nginxconf['KEEPWEBSSLPORT'])
643 _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
644 _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
647 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
649 kill_server_pid(_pidfile('nginx'))
651 def _pidfile(program):
652 return os.path.join(TEST_TMPDIR, program + '.pid')
654 def _portfile(program):
655 return os.path.join(TEST_TMPDIR, program + '.port')
657 def _setport(program, port):
658 with open(_portfile(program), 'w') as f:
661 # Returns 9 if program is not up.
662 def _getport(program):
664 return int(open(_portfile(program)).read())
669 global _cached_db_config
670 if not _cached_db_config:
671 _cached_db_config = yaml.load(open(os.path.join(
672 SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
673 return _cached_db_config['test'][key]
676 global _cached_config
678 return _cached_config[key]
679 def _load(f, required=True):
680 fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
681 if not required and not os.path.exists(fullpath):
683 return yaml.load(fullpath)
684 cdefault = _load('application.default.yml')
685 csite = _load('application.yml', required=False)
687 for section in [cdefault.get('common',{}), cdefault.get('test',{}),
688 csite.get('common',{}), csite.get('test',{})]:
689 _cached_config.update(section)
690 return _cached_config[key]
693 '''load a fixture yaml file'''
694 with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
698 trim_index = yaml_file.index("# Test Helper trims the rest of the file")
699 yaml_file = yaml_file[0:trim_index]
702 return yaml.load(yaml_file)
704 def auth_token(token_name):
705 return fixture("api_client_authorizations")[token_name]["api_token"]
707 def authorize_with(token_name):
708 '''token_name is the symbolic name of the token from the api_client_authorizations fixture'''
709 arvados.config.settings()["ARVADOS_API_TOKEN"] = auth_token(token_name)
710 arvados.config.settings()["ARVADOS_API_HOST"] = os.environ.get("ARVADOS_API_HOST")
711 arvados.config.settings()["ARVADOS_API_HOST_INSECURE"] = "true"
713 class TestCaseWithServers(unittest.TestCase):
714 """TestCase to start and stop supporting Arvados servers.
716 Define any of MAIN_SERVER, KEEP_SERVER, and/or KEEP_PROXY_SERVER
717 class variables as a dictionary of keyword arguments. If you do,
718 setUpClass will start the corresponding servers by passing these
719 keyword arguments to the run, run_keep, and/or run_keep_server
720 functions, respectively. It will also set Arvados environment
721 variables to point to these servers appropriately. If you don't
722 run a Keep or Keep proxy server, setUpClass will set up a
723 temporary directory for Keep local storage, and set it as
726 tearDownClass will stop any servers started, and restore the
727 original environment.
732 KEEP_PROXY_SERVER = None
733 KEEP_WEB_SERVER = None
736 def _restore_dict(src, dest):
737 for key in list(dest.keys()):
744 cls._orig_environ = os.environ.copy()
745 cls._orig_config = arvados.config.settings().copy()
746 cls._cleanup_funcs = []
747 os.environ.pop('ARVADOS_KEEP_SERVICES', None)
748 os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
749 for server_kwargs, start_func, stop_func in (
750 (cls.MAIN_SERVER, run, reset),
751 (cls.WS_SERVER, run_ws, stop_ws),
752 (cls.KEEP_SERVER, run_keep, stop_keep),
753 (cls.KEEP_PROXY_SERVER, run_keep_proxy, stop_keep_proxy),
754 (cls.KEEP_WEB_SERVER, run_keep_web, stop_keep_web)):
755 if server_kwargs is not None:
756 start_func(**server_kwargs)
757 cls._cleanup_funcs.append(stop_func)
758 if (cls.KEEP_SERVER is None) and (cls.KEEP_PROXY_SERVER is None):
759 cls.local_store = tempfile.mkdtemp()
760 os.environ['KEEP_LOCAL_STORE'] = cls.local_store
761 cls._cleanup_funcs.append(
762 lambda: shutil.rmtree(cls.local_store, ignore_errors=True))
764 os.environ.pop('KEEP_LOCAL_STORE', None)
765 arvados.config.initialize()
768 def tearDownClass(cls):
769 for clean_func in cls._cleanup_funcs:
771 cls._restore_dict(cls._orig_environ, os.environ)
772 cls._restore_dict(cls._orig_config, arvados.config.settings())
775 if __name__ == "__main__":
778 'start_ws', 'stop_ws',
779 'start_keep', 'stop_keep',
780 'start_keep_proxy', 'stop_keep_proxy',
781 'start_keep-web', 'stop_keep-web',
782 'start_arv-git-httpd', 'stop_arv-git-httpd',
783 'start_nginx', 'stop_nginx',
785 parser = argparse.ArgumentParser()
786 parser.add_argument('action', type=str, help="one of {}".format(actions))
787 parser.add_argument('--auth', type=str, metavar='FIXTURE_NAME', help='Print authorization info for given api_client_authorizations fixture')
788 parser.add_argument('--num-keep-servers', metavar='int', type=int, default=2, help="Number of keep servers desired")
789 parser.add_argument('--keep-enforce-permissions', action="store_true", help="Enforce keep permissions")
791 args = parser.parse_args()
793 if args.action not in actions:
794 print("Unrecognized action '{}'. Actions are: {}.".
795 format(args.action, actions),
798 if args.action == 'start':
799 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
800 run(leave_running_atexit=True)
801 host = os.environ['ARVADOS_API_HOST']
802 if args.auth is not None:
803 token = auth_token(args.auth)
804 print("export ARVADOS_API_TOKEN={}".format(pipes.quote(token)))
805 print("export ARVADOS_API_HOST={}".format(pipes.quote(host)))
806 print("export ARVADOS_API_HOST_INSECURE=true")
809 elif args.action == 'stop':
810 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
811 elif args.action == 'start_ws':
813 elif args.action == 'stop_ws':
815 elif args.action == 'start_keep':
816 run_keep(enforce_permissions=args.keep_enforce_permissions, num_servers=args.num_keep_servers)
817 elif args.action == 'stop_keep':
818 stop_keep(num_servers=args.num_keep_servers)
819 elif args.action == 'start_keep_proxy':
821 elif args.action == 'stop_keep_proxy':
823 elif args.action == 'start_arv-git-httpd':
825 elif args.action == 'stop_arv-git-httpd':
827 elif args.action == 'start_keep-web':
829 elif args.action == 'stop_keep-web':
831 elif args.action == 'start_nginx':
833 elif args.action == 'stop_nginx':
836 raise Exception("action recognized but not implemented!?")