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(arvados.http_cache('discovery'),
243 '*,arvados,v1,rest,*')):
246 pid_file = _pidfile('api')
247 pid_file_ok = find_server_pid(pid_file, 0)
249 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
250 if existing_api_host and pid_file_ok:
251 if existing_api_host == my_api_host:
255 # Fall through to shutdown-and-start case.
258 # Server was provided by parent. Can't recover if it's
262 # Before trying to start up our own server, call stop() to avoid
263 # "Phusion Passenger Standalone is already running on PID 12345".
264 # (If we've gotten this far, ARVADOS_TEST_API_HOST isn't set, so
265 # we know the server is ours to kill.)
268 restore_cwd = os.getcwd()
269 api_src_dir = os.path.join(SERVICES_SRC_DIR, 'api')
270 os.chdir(api_src_dir)
272 # Either we haven't started a server of our own yet, or it has
273 # died, or we have lost our credentials, or something else is
274 # preventing us from calling reset(). Start a new one.
276 if not os.path.exists('tmp'):
279 if not os.path.exists('tmp/api'):
280 os.makedirs('tmp/api')
282 if not os.path.exists('tmp/logs'):
283 os.makedirs('tmp/logs')
285 if not os.path.exists('tmp/self-signed.pem'):
286 # We assume here that either passenger reports its listening
287 # address as https:/0.0.0.0:port/. If it reports "127.0.0.1"
288 # then the certificate won't match the host and reset() will
289 # fail certificate verification. If it reports "localhost",
290 # clients (notably Python SDK's websocket client) might
291 # resolve localhost as ::1 and then fail to connect.
292 subprocess.check_call([
293 'openssl', 'req', '-new', '-x509', '-nodes',
294 '-out', 'tmp/self-signed.pem',
295 '-keyout', 'tmp/self-signed.key',
297 '-subj', '/CN=0.0.0.0'],
300 # Install the git repository fixtures.
301 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
302 gittarball = os.path.join(SERVICES_SRC_DIR, 'api', 'test', 'test.git.tar')
303 if not os.path.isdir(gitdir):
305 subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
307 # The nginx proxy isn't listening here yet, but we need to choose
308 # the wss:// port now so we can write the API server config file.
309 wss_port = find_available_port()
310 _setport('wss', wss_port)
312 port = find_available_port()
313 env = os.environ.copy()
314 env['RAILS_ENV'] = 'test'
315 env['ARVADOS_TEST_WSS_PORT'] = str(wss_port)
316 if env.get('ARVADOS_TEST_EXPERIMENTAL_WS'):
317 env.pop('ARVADOS_WEBSOCKETS', None)
319 env['ARVADOS_WEBSOCKETS'] = 'yes'
320 env.pop('ARVADOS_TEST_API_HOST', None)
321 env.pop('ARVADOS_API_HOST', None)
322 env.pop('ARVADOS_API_HOST_INSECURE', None)
323 env.pop('ARVADOS_API_TOKEN', None)
324 start_msg = subprocess.check_output(
326 'passenger', 'start', '-d', '-p{}'.format(port),
327 '--pid-file', pid_file,
328 '--log-file', os.path.join(os.getcwd(), 'log/test.log'),
330 '--ssl-certificate', 'tmp/self-signed.pem',
331 '--ssl-certificate-key', 'tmp/self-signed.key'],
334 if not leave_running_atexit:
335 atexit.register(kill_server_pid, pid_file, passenger_root=api_src_dir)
337 match = re.search(r'Accessible via: https://(.*?)/', start_msg)
340 "Passenger did not report endpoint: {}".format(start_msg))
341 my_api_host = match.group(1)
342 os.environ['ARVADOS_API_HOST'] = my_api_host
344 # Make sure the server has written its pid file and started
345 # listening on its TCP port
346 find_server_pid(pid_file)
347 _wait_until_port_listens(port)
350 os.chdir(restore_cwd)
353 """Reset the test server to fixture state.
355 This resets the ARVADOS_TEST_API_HOST provided by a parent process
356 if any, otherwise the server started by run().
358 It also resets ARVADOS_* environment vars to point to the test
359 server with admin credentials.
361 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
362 token = auth_token('admin')
363 httpclient = httplib2.Http(ca_certs=os.path.join(
364 SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem'))
366 'https://{}/database/reset'.format(existing_api_host),
368 headers={'Authorization': 'OAuth2 {}'.format(token)})
369 os.environ['ARVADOS_API_HOST_INSECURE'] = 'true'
370 os.environ['ARVADOS_API_HOST'] = existing_api_host
371 os.environ['ARVADOS_API_TOKEN'] = token
373 def stop(force=False):
374 """Stop the API server, if one is running.
376 If force==False, kill it only if we started it ourselves. (This
377 supports the use case where a Python test suite calls run(), but
378 run() just uses the ARVADOS_TEST_API_HOST provided by the parent
379 process, and the test suite cleans up after itself by calling
380 stop(). In this case the test server provided by the parent
381 process should be left alone.)
383 If force==True, kill it even if we didn't start it
384 ourselves. (This supports the use case in __main__, where "run"
385 and "stop" happen in different processes.)
388 if force or my_api_host is not None:
389 kill_server_pid(_pidfile('api'))
393 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
396 port = find_available_port()
397 conf = os.path.join(TEST_TMPDIR, 'ws.yml')
398 with open(conf, 'w') as f:
411 """.format(os.environ['ARVADOS_API_HOST'],
413 ('info' if os.environ.get('ARVADOS_DEBUG', '') in ['','0'] else 'debug'),
415 _dbconfig('database'),
416 _dbconfig('username'),
417 _dbconfig('password')))
418 logf = open(_fifo2stderr('ws'), 'w')
419 ws = subprocess.Popen(
420 ["ws", "-config", conf],
421 stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
422 with open(_pidfile('ws'), 'w') as f:
424 _wait_until_port_listens(port)
429 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
431 kill_server_pid(_pidfile('ws'))
433 def _start_keep(n, keep_args):
434 keep0 = tempfile.mkdtemp()
435 port = find_available_port()
436 keep_cmd = ["keepstore",
437 "-volume={}".format(keep0),
438 "-listen=:{}".format(port),
439 "-pid="+_pidfile('keep{}'.format(n))]
441 for arg, val in keep_args.iteritems():
442 keep_cmd.append("{}={}".format(arg, val))
444 logf = open(_fifo2stderr('keep{}'.format(n)), 'w')
445 kp0 = subprocess.Popen(
446 keep_cmd, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
448 with open(_pidfile('keep{}'.format(n)), 'w') as f:
449 f.write(str(kp0.pid))
451 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'w') as f:
454 _wait_until_port_listens(port)
458 def run_keep(blob_signing_key=None, enforce_permissions=False, num_servers=2):
459 stop_keep(num_servers)
462 if not blob_signing_key:
463 blob_signing_key = 'zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc'
464 with open(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"), "w") as f:
465 keep_args['-blob-signing-key-file'] = f.name
466 f.write(blob_signing_key)
467 keep_args['-enforce-permissions'] = str(enforce_permissions).lower()
468 with open(os.path.join(TEST_TMPDIR, "keep.data-manager-token-file"), "w") as f:
469 keep_args['-data-manager-token-file'] = f.name
470 f.write(auth_token('data_manager'))
471 keep_args['-never-delete'] = 'false'
475 host=os.environ['ARVADOS_API_HOST'],
476 token=os.environ['ARVADOS_API_TOKEN'],
479 for d in api.keep_services().list(filters=[['service_type','=','disk']]).execute()['items']:
480 api.keep_services().delete(uuid=d['uuid']).execute()
481 for d in api.keep_disks().list().execute()['items']:
482 api.keep_disks().delete(uuid=d['uuid']).execute()
484 for d in range(0, num_servers):
485 port = _start_keep(d, keep_args)
486 svc = api.keep_services().create(body={'keep_service': {
487 'uuid': 'zzzzz-bi6l4-keepdisk{:07d}'.format(d),
488 'service_host': 'localhost',
489 'service_port': port,
490 'service_type': 'disk',
491 'service_ssl_flag': False,
493 api.keep_disks().create(body={
494 'keep_disk': {'keep_service_uuid': svc['uuid'] }
497 # If keepproxy is running, send SIGHUP to make it discover the new
498 # keepstore services.
499 proxypidfile = _pidfile('keepproxy')
500 if os.path.exists(proxypidfile):
502 os.kill(int(open(proxypidfile).read()), signal.SIGHUP)
504 os.remove(proxypidfile)
507 kill_server_pid(_pidfile('keep{}'.format(n)))
508 if os.path.exists("{}/keep{}.volume".format(TEST_TMPDIR, n)):
509 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'r') as r:
510 shutil.rmtree(r.read(), True)
511 os.unlink("{}/keep{}.volume".format(TEST_TMPDIR, n))
512 if os.path.exists(os.path.join(TEST_TMPDIR, "keep.blob_signing_key")):
513 os.remove(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"))
515 def stop_keep(num_servers=2):
516 for n in range(0, num_servers):
519 def run_keep_proxy():
520 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
524 port = find_available_port()
525 env = os.environ.copy()
526 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
527 logf = open(_fifo2stderr('keepproxy'), 'w')
528 kp = subprocess.Popen(
530 '-pid='+_pidfile('keepproxy'),
531 '-listen=:{}'.format(port)],
532 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
536 host=os.environ['ARVADOS_API_HOST'],
537 token=auth_token('admin'),
539 for d in api.keep_services().list(
540 filters=[['service_type','=','proxy']]).execute()['items']:
541 api.keep_services().delete(uuid=d['uuid']).execute()
542 api.keep_services().create(body={'keep_service': {
543 'service_host': 'localhost',
544 'service_port': port,
545 'service_type': 'proxy',
546 'service_ssl_flag': False,
548 os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(port)
549 _setport('keepproxy', port)
550 _wait_until_port_listens(port)
552 def stop_keep_proxy():
553 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
555 kill_server_pid(_pidfile('keepproxy'))
557 def run_arv_git_httpd():
558 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
562 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
563 gitport = find_available_port()
564 env = os.environ.copy()
565 env.pop('ARVADOS_API_TOKEN', None)
566 logf = open(_fifo2stderr('arv-git-httpd'), 'w')
567 agh = subprocess.Popen(
569 '-repo-root='+gitdir+'/test',
570 '-address=:'+str(gitport)],
571 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
572 with open(_pidfile('arv-git-httpd'), 'w') as f:
573 f.write(str(agh.pid))
574 _setport('arv-git-httpd', gitport)
575 _wait_until_port_listens(gitport)
577 def stop_arv_git_httpd():
578 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
580 kill_server_pid(_pidfile('arv-git-httpd'))
583 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
587 keepwebport = find_available_port()
588 env = os.environ.copy()
589 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
590 logf = open(_fifo2stderr('keep-web'), 'w')
591 keepweb = subprocess.Popen(
594 '-attachment-only-host=download:'+str(keepwebport),
595 '-listen=:'+str(keepwebport)],
596 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
597 with open(_pidfile('keep-web'), 'w') as f:
598 f.write(str(keepweb.pid))
599 _setport('keep-web', keepwebport)
600 _wait_until_port_listens(keepwebport)
603 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
605 kill_server_pid(_pidfile('keep-web'))
608 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
612 nginxconf['KEEPWEBPORT'] = _getport('keep-web')
613 nginxconf['KEEPWEBDLSSLPORT'] = find_available_port()
614 nginxconf['KEEPWEBSSLPORT'] = find_available_port()
615 nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
616 nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
617 nginxconf['GITPORT'] = _getport('arv-git-httpd')
618 nginxconf['GITSSLPORT'] = find_available_port()
619 nginxconf['WSPORT'] = _getport('ws')
620 nginxconf['WSSPORT'] = _getport('wss')
621 nginxconf['SSLCERT'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem')
622 nginxconf['SSLKEY'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.key')
623 nginxconf['ACCESSLOG'] = _fifo2stderr('nginx_access_log')
625 conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
626 conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
627 with open(conffile, 'w') as f:
630 lambda match: str(nginxconf.get(match.group(1))),
631 open(conftemplatefile).read()))
633 env = os.environ.copy()
634 env['PATH'] = env['PATH']+':/sbin:/usr/sbin:/usr/local/sbin'
636 nginx = subprocess.Popen(
638 '-g', 'error_log stderr info;',
639 '-g', 'pid '+_pidfile('nginx')+';',
641 env=env, stdin=open('/dev/null'), stdout=sys.stderr)
642 _setport('keep-web-dl-ssl', nginxconf['KEEPWEBDLSSLPORT'])
643 _setport('keep-web-ssl', nginxconf['KEEPWEBSSLPORT'])
644 _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
645 _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
648 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
650 kill_server_pid(_pidfile('nginx'))
652 def _pidfile(program):
653 return os.path.join(TEST_TMPDIR, program + '.pid')
655 def _portfile(program):
656 return os.path.join(TEST_TMPDIR, program + '.port')
658 def _setport(program, port):
659 with open(_portfile(program), 'w') as f:
662 # Returns 9 if program is not up.
663 def _getport(program):
665 return int(open(_portfile(program)).read())
670 global _cached_db_config
671 if not _cached_db_config:
672 _cached_db_config = yaml.load(open(os.path.join(
673 SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
674 return _cached_db_config['test'][key]
677 global _cached_config
679 return _cached_config[key]
680 def _load(f, required=True):
681 fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
682 if not required and not os.path.exists(fullpath):
684 return yaml.load(fullpath)
685 cdefault = _load('application.default.yml')
686 csite = _load('application.yml', required=False)
688 for section in [cdefault.get('common',{}), cdefault.get('test',{}),
689 csite.get('common',{}), csite.get('test',{})]:
690 _cached_config.update(section)
691 return _cached_config[key]
694 '''load a fixture yaml file'''
695 with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
699 trim_index = yaml_file.index("# Test Helper trims the rest of the file")
700 yaml_file = yaml_file[0:trim_index]
703 return yaml.load(yaml_file)
705 def auth_token(token_name):
706 return fixture("api_client_authorizations")[token_name]["api_token"]
708 def authorize_with(token_name):
709 '''token_name is the symbolic name of the token from the api_client_authorizations fixture'''
710 arvados.config.settings()["ARVADOS_API_TOKEN"] = auth_token(token_name)
711 arvados.config.settings()["ARVADOS_API_HOST"] = os.environ.get("ARVADOS_API_HOST")
712 arvados.config.settings()["ARVADOS_API_HOST_INSECURE"] = "true"
714 class TestCaseWithServers(unittest.TestCase):
715 """TestCase to start and stop supporting Arvados servers.
717 Define any of MAIN_SERVER, KEEP_SERVER, and/or KEEP_PROXY_SERVER
718 class variables as a dictionary of keyword arguments. If you do,
719 setUpClass will start the corresponding servers by passing these
720 keyword arguments to the run, run_keep, and/or run_keep_server
721 functions, respectively. It will also set Arvados environment
722 variables to point to these servers appropriately. If you don't
723 run a Keep or Keep proxy server, setUpClass will set up a
724 temporary directory for Keep local storage, and set it as
727 tearDownClass will stop any servers started, and restore the
728 original environment.
733 KEEP_PROXY_SERVER = None
734 KEEP_WEB_SERVER = None
737 def _restore_dict(src, dest):
738 for key in dest.keys():
745 cls._orig_environ = os.environ.copy()
746 cls._orig_config = arvados.config.settings().copy()
747 cls._cleanup_funcs = []
748 os.environ.pop('ARVADOS_KEEP_SERVICES', None)
749 os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
750 for server_kwargs, start_func, stop_func in (
751 (cls.MAIN_SERVER, run, reset),
752 (cls.WS_SERVER, run_ws, stop_ws),
753 (cls.KEEP_SERVER, run_keep, stop_keep),
754 (cls.KEEP_PROXY_SERVER, run_keep_proxy, stop_keep_proxy),
755 (cls.KEEP_WEB_SERVER, run_keep_web, stop_keep_web)):
756 if server_kwargs is not None:
757 start_func(**server_kwargs)
758 cls._cleanup_funcs.append(stop_func)
759 if (cls.KEEP_SERVER is None) and (cls.KEEP_PROXY_SERVER is None):
760 cls.local_store = tempfile.mkdtemp()
761 os.environ['KEEP_LOCAL_STORE'] = cls.local_store
762 cls._cleanup_funcs.append(
763 lambda: shutil.rmtree(cls.local_store, ignore_errors=True))
765 os.environ.pop('KEEP_LOCAL_STORE', None)
766 arvados.config.initialize()
769 def tearDownClass(cls):
770 for clean_func in cls._cleanup_funcs:
772 cls._restore_dict(cls._orig_environ, os.environ)
773 cls._restore_dict(cls._orig_config, arvados.config.settings())
776 if __name__ == "__main__":
779 'start_ws', 'stop_ws',
780 'start_keep', 'stop_keep',
781 'start_keep_proxy', 'stop_keep_proxy',
782 'start_keep-web', 'stop_keep-web',
783 'start_arv-git-httpd', 'stop_arv-git-httpd',
784 'start_nginx', 'stop_nginx',
786 parser = argparse.ArgumentParser()
787 parser.add_argument('action', type=str, help="one of {}".format(actions))
788 parser.add_argument('--auth', type=str, metavar='FIXTURE_NAME', help='Print authorization info for given api_client_authorizations fixture')
789 parser.add_argument('--num-keep-servers', metavar='int', type=int, default=2, help="Number of keep servers desired")
790 parser.add_argument('--keep-enforce-permissions', action="store_true", help="Enforce keep permissions")
792 args = parser.parse_args()
794 if args.action not in actions:
795 print("Unrecognized action '{}'. Actions are: {}.".
796 format(args.action, actions),
799 if args.action == 'start':
800 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
801 run(leave_running_atexit=True)
802 host = os.environ['ARVADOS_API_HOST']
803 if args.auth is not None:
804 token = auth_token(args.auth)
805 print("export ARVADOS_API_TOKEN={}".format(pipes.quote(token)))
806 print("export ARVADOS_API_HOST={}".format(pipes.quote(host)))
807 print("export ARVADOS_API_HOST_INSECURE=true")
810 elif args.action == 'stop':
811 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
812 elif args.action == 'start_ws':
814 elif args.action == 'stop_ws':
816 elif args.action == 'start_keep':
817 run_keep(enforce_permissions=args.keep_enforce_permissions, num_servers=args.num_keep_servers)
818 elif args.action == 'stop_keep':
819 stop_keep(num_servers=args.num_keep_servers)
820 elif args.action == 'start_keep_proxy':
822 elif args.action == 'stop_keep_proxy':
824 elif args.action == 'start_arv-git-httpd':
826 elif args.action == 'stop_arv-git-httpd':
828 elif args.action == 'start_keep-web':
830 elif args.action == 'stop_keep-web':
832 elif args.action == 'start_nginx':
834 elif args.action == 'stop_nginx':
837 raise Exception("action recognized but not implemented!?")