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 if env.get('ARVADOS_TEST_EXPERIMENTAL_WS'):
318 env.pop('ARVADOS_WEBSOCKETS', None)
320 env['ARVADOS_WEBSOCKETS'] = 'yes'
321 env.pop('ARVADOS_TEST_API_HOST', None)
322 env.pop('ARVADOS_API_HOST', None)
323 env.pop('ARVADOS_API_HOST_INSECURE', None)
324 env.pop('ARVADOS_API_TOKEN', None)
325 start_msg = subprocess.check_output(
327 'passenger', 'start', '-d', '-p{}'.format(port),
328 '--pid-file', pid_file,
329 '--log-file', os.path.join(os.getcwd(), 'log/test.log'),
331 '--ssl-certificate', 'tmp/self-signed.pem',
332 '--ssl-certificate-key', 'tmp/self-signed.key'],
335 if not leave_running_atexit:
336 atexit.register(kill_server_pid, pid_file, passenger_root=api_src_dir)
338 match = re.search(r'Accessible via: https://(.*?)/', start_msg)
341 "Passenger did not report endpoint: {}".format(start_msg))
342 my_api_host = match.group(1)
343 os.environ['ARVADOS_API_HOST'] = my_api_host
345 # Make sure the server has written its pid file and started
346 # listening on its TCP port
347 find_server_pid(pid_file)
348 _wait_until_port_listens(port)
351 os.chdir(restore_cwd)
354 """Reset the test server to fixture state.
356 This resets the ARVADOS_TEST_API_HOST provided by a parent process
357 if any, otherwise the server started by run().
359 It also resets ARVADOS_* environment vars to point to the test
360 server with admin credentials.
362 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
363 token = auth_token('admin')
364 httpclient = httplib2.Http(ca_certs=os.path.join(
365 SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem'))
367 'https://{}/database/reset'.format(existing_api_host),
369 headers={'Authorization': 'OAuth2 {}'.format(token)})
370 os.environ['ARVADOS_API_HOST_INSECURE'] = 'true'
371 os.environ['ARVADOS_API_HOST'] = existing_api_host
372 os.environ['ARVADOS_API_TOKEN'] = token
374 def stop(force=False):
375 """Stop the API server, if one is running.
377 If force==False, kill it only if we started it ourselves. (This
378 supports the use case where a Python test suite calls run(), but
379 run() just uses the ARVADOS_TEST_API_HOST provided by the parent
380 process, and the test suite cleans up after itself by calling
381 stop(). In this case the test server provided by the parent
382 process should be left alone.)
384 If force==True, kill it even if we didn't start it
385 ourselves. (This supports the use case in __main__, where "run"
386 and "stop" happen in different processes.)
389 if force or my_api_host is not None:
390 kill_server_pid(_pidfile('api'))
394 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
397 port = find_available_port()
398 conf = os.path.join(TEST_TMPDIR, 'ws.yml')
399 with open(conf, 'w') as f:
412 """.format(os.environ['ARVADOS_API_HOST'],
414 ('info' if os.environ.get('ARVADOS_DEBUG', '') in ['','0'] else 'debug'),
416 _dbconfig('database'),
417 _dbconfig('username'),
418 _dbconfig('password')))
419 logf = open(_fifo2stderr('ws'), 'w')
420 ws = subprocess.Popen(
421 ["ws", "-config", conf],
422 stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
423 with open(_pidfile('ws'), 'w') as f:
425 _wait_until_port_listens(port)
430 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
432 kill_server_pid(_pidfile('ws'))
434 def _start_keep(n, keep_args):
435 keep0 = tempfile.mkdtemp()
436 port = find_available_port()
437 keep_cmd = ["keepstore",
438 "-volume={}".format(keep0),
439 "-listen=:{}".format(port),
440 "-pid="+_pidfile('keep{}'.format(n))]
442 for arg, val in keep_args.iteritems():
443 keep_cmd.append("{}={}".format(arg, val))
445 logf = open(_fifo2stderr('keep{}'.format(n)), 'w')
446 kp0 = subprocess.Popen(
447 keep_cmd, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
449 with open(_pidfile('keep{}'.format(n)), 'w') as f:
450 f.write(str(kp0.pid))
452 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'w') as f:
455 _wait_until_port_listens(port)
459 def run_keep(blob_signing_key=None, enforce_permissions=False, num_servers=2):
460 stop_keep(num_servers)
463 if not blob_signing_key:
464 blob_signing_key = 'zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc'
465 with open(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"), "w") as f:
466 keep_args['-blob-signing-key-file'] = f.name
467 f.write(blob_signing_key)
468 keep_args['-enforce-permissions'] = str(enforce_permissions).lower()
469 with open(os.path.join(TEST_TMPDIR, "keep.data-manager-token-file"), "w") as f:
470 keep_args['-data-manager-token-file'] = f.name
471 f.write(auth_token('data_manager'))
472 keep_args['-never-delete'] = 'false'
476 host=os.environ['ARVADOS_API_HOST'],
477 token=os.environ['ARVADOS_API_TOKEN'],
480 for d in api.keep_services().list(filters=[['service_type','=','disk']]).execute()['items']:
481 api.keep_services().delete(uuid=d['uuid']).execute()
482 for d in api.keep_disks().list().execute()['items']:
483 api.keep_disks().delete(uuid=d['uuid']).execute()
485 for d in range(0, num_servers):
486 port = _start_keep(d, keep_args)
487 svc = api.keep_services().create(body={'keep_service': {
488 'uuid': 'zzzzz-bi6l4-keepdisk{:07d}'.format(d),
489 'service_host': 'localhost',
490 'service_port': port,
491 'service_type': 'disk',
492 'service_ssl_flag': False,
494 api.keep_disks().create(body={
495 'keep_disk': {'keep_service_uuid': svc['uuid'] }
498 # If keepproxy is running, send SIGHUP to make it discover the new
499 # keepstore services.
500 proxypidfile = _pidfile('keepproxy')
501 if os.path.exists(proxypidfile):
503 os.kill(int(open(proxypidfile).read()), signal.SIGHUP)
505 os.remove(proxypidfile)
508 kill_server_pid(_pidfile('keep{}'.format(n)))
509 if os.path.exists("{}/keep{}.volume".format(TEST_TMPDIR, n)):
510 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'r') as r:
511 shutil.rmtree(r.read(), True)
512 os.unlink("{}/keep{}.volume".format(TEST_TMPDIR, n))
513 if os.path.exists(os.path.join(TEST_TMPDIR, "keep.blob_signing_key")):
514 os.remove(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"))
516 def stop_keep(num_servers=2):
517 for n in range(0, num_servers):
520 def run_keep_proxy():
521 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
525 port = find_available_port()
526 env = os.environ.copy()
527 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
528 logf = open(_fifo2stderr('keepproxy'), 'w')
529 kp = subprocess.Popen(
531 '-pid='+_pidfile('keepproxy'),
532 '-listen=:{}'.format(port)],
533 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
537 host=os.environ['ARVADOS_API_HOST'],
538 token=auth_token('admin'),
540 for d in api.keep_services().list(
541 filters=[['service_type','=','proxy']]).execute()['items']:
542 api.keep_services().delete(uuid=d['uuid']).execute()
543 api.keep_services().create(body={'keep_service': {
544 'service_host': 'localhost',
545 'service_port': port,
546 'service_type': 'proxy',
547 'service_ssl_flag': False,
549 os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(port)
550 _setport('keepproxy', port)
551 _wait_until_port_listens(port)
553 def stop_keep_proxy():
554 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
556 kill_server_pid(_pidfile('keepproxy'))
558 def run_arv_git_httpd():
559 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
563 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
564 gitport = find_available_port()
565 env = os.environ.copy()
566 env.pop('ARVADOS_API_TOKEN', None)
567 logf = open(_fifo2stderr('arv-git-httpd'), 'w')
568 agh = subprocess.Popen(
570 '-repo-root='+gitdir+'/test',
571 '-address=:'+str(gitport)],
572 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
573 with open(_pidfile('arv-git-httpd'), 'w') as f:
574 f.write(str(agh.pid))
575 _setport('arv-git-httpd', gitport)
576 _wait_until_port_listens(gitport)
578 def stop_arv_git_httpd():
579 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
581 kill_server_pid(_pidfile('arv-git-httpd'))
584 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
588 keepwebport = find_available_port()
589 env = os.environ.copy()
590 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
591 logf = open(_fifo2stderr('keep-web'), 'w')
592 keepweb = subprocess.Popen(
595 '-attachment-only-host=download:'+str(keepwebport),
596 '-listen=:'+str(keepwebport)],
597 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
598 with open(_pidfile('keep-web'), 'w') as f:
599 f.write(str(keepweb.pid))
600 _setport('keep-web', keepwebport)
601 _wait_until_port_listens(keepwebport)
604 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
606 kill_server_pid(_pidfile('keep-web'))
609 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
613 nginxconf['KEEPWEBPORT'] = _getport('keep-web')
614 nginxconf['KEEPWEBDLSSLPORT'] = find_available_port()
615 nginxconf['KEEPWEBSSLPORT'] = find_available_port()
616 nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
617 nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
618 nginxconf['GITPORT'] = _getport('arv-git-httpd')
619 nginxconf['GITSSLPORT'] = find_available_port()
620 nginxconf['WSPORT'] = _getport('ws')
621 nginxconf['WSSPORT'] = _getport('wss')
622 nginxconf['SSLCERT'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem')
623 nginxconf['SSLKEY'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.key')
624 nginxconf['ACCESSLOG'] = _fifo2stderr('nginx_access_log')
626 conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
627 conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
628 with open(conffile, 'w') as f:
631 lambda match: str(nginxconf.get(match.group(1))),
632 open(conftemplatefile).read()))
634 env = os.environ.copy()
635 env['PATH'] = env['PATH']+':/sbin:/usr/sbin:/usr/local/sbin'
637 nginx = subprocess.Popen(
639 '-g', 'error_log stderr info;',
640 '-g', 'pid '+_pidfile('nginx')+';',
642 env=env, stdin=open('/dev/null'), stdout=sys.stderr)
643 _setport('keep-web-dl-ssl', nginxconf['KEEPWEBDLSSLPORT'])
644 _setport('keep-web-ssl', nginxconf['KEEPWEBSSLPORT'])
645 _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
646 _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
649 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
651 kill_server_pid(_pidfile('nginx'))
653 def _pidfile(program):
654 return os.path.join(TEST_TMPDIR, program + '.pid')
656 def _portfile(program):
657 return os.path.join(TEST_TMPDIR, program + '.port')
659 def _setport(program, port):
660 with open(_portfile(program), 'w') as f:
663 # Returns 9 if program is not up.
664 def _getport(program):
666 return int(open(_portfile(program)).read())
671 global _cached_db_config
672 if not _cached_db_config:
673 _cached_db_config = yaml.load(open(os.path.join(
674 SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
675 return _cached_db_config['test'][key]
678 global _cached_config
680 return _cached_config[key]
681 def _load(f, required=True):
682 fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
683 if not required and not os.path.exists(fullpath):
685 return yaml.load(fullpath)
686 cdefault = _load('application.default.yml')
687 csite = _load('application.yml', required=False)
689 for section in [cdefault.get('common',{}), cdefault.get('test',{}),
690 csite.get('common',{}), csite.get('test',{})]:
691 _cached_config.update(section)
692 return _cached_config[key]
695 '''load a fixture yaml file'''
696 with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
700 trim_index = yaml_file.index("# Test Helper trims the rest of the file")
701 yaml_file = yaml_file[0:trim_index]
704 return yaml.load(yaml_file)
706 def auth_token(token_name):
707 return fixture("api_client_authorizations")[token_name]["api_token"]
709 def authorize_with(token_name):
710 '''token_name is the symbolic name of the token from the api_client_authorizations fixture'''
711 arvados.config.settings()["ARVADOS_API_TOKEN"] = auth_token(token_name)
712 arvados.config.settings()["ARVADOS_API_HOST"] = os.environ.get("ARVADOS_API_HOST")
713 arvados.config.settings()["ARVADOS_API_HOST_INSECURE"] = "true"
715 class TestCaseWithServers(unittest.TestCase):
716 """TestCase to start and stop supporting Arvados servers.
718 Define any of MAIN_SERVER, KEEP_SERVER, and/or KEEP_PROXY_SERVER
719 class variables as a dictionary of keyword arguments. If you do,
720 setUpClass will start the corresponding servers by passing these
721 keyword arguments to the run, run_keep, and/or run_keep_server
722 functions, respectively. It will also set Arvados environment
723 variables to point to these servers appropriately. If you don't
724 run a Keep or Keep proxy server, setUpClass will set up a
725 temporary directory for Keep local storage, and set it as
728 tearDownClass will stop any servers started, and restore the
729 original environment.
734 KEEP_PROXY_SERVER = None
735 KEEP_WEB_SERVER = None
738 def _restore_dict(src, dest):
739 for key in dest.keys():
746 cls._orig_environ = os.environ.copy()
747 cls._orig_config = arvados.config.settings().copy()
748 cls._cleanup_funcs = []
749 os.environ.pop('ARVADOS_KEEP_SERVICES', None)
750 os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
751 for server_kwargs, start_func, stop_func in (
752 (cls.MAIN_SERVER, run, reset),
753 (cls.WS_SERVER, run_ws, stop_ws),
754 (cls.KEEP_SERVER, run_keep, stop_keep),
755 (cls.KEEP_PROXY_SERVER, run_keep_proxy, stop_keep_proxy),
756 (cls.KEEP_WEB_SERVER, run_keep_web, stop_keep_web)):
757 if server_kwargs is not None:
758 start_func(**server_kwargs)
759 cls._cleanup_funcs.append(stop_func)
760 if (cls.KEEP_SERVER is None) and (cls.KEEP_PROXY_SERVER is None):
761 cls.local_store = tempfile.mkdtemp()
762 os.environ['KEEP_LOCAL_STORE'] = cls.local_store
763 cls._cleanup_funcs.append(
764 lambda: shutil.rmtree(cls.local_store, ignore_errors=True))
766 os.environ.pop('KEEP_LOCAL_STORE', None)
767 arvados.config.initialize()
770 def tearDownClass(cls):
771 for clean_func in cls._cleanup_funcs:
773 cls._restore_dict(cls._orig_environ, os.environ)
774 cls._restore_dict(cls._orig_config, arvados.config.settings())
777 if __name__ == "__main__":
780 'start_ws', 'stop_ws',
781 'start_keep', 'stop_keep',
782 'start_keep_proxy', 'stop_keep_proxy',
783 'start_keep-web', 'stop_keep-web',
784 'start_arv-git-httpd', 'stop_arv-git-httpd',
785 'start_nginx', 'stop_nginx',
787 parser = argparse.ArgumentParser()
788 parser.add_argument('action', type=str, help="one of {}".format(actions))
789 parser.add_argument('--auth', type=str, metavar='FIXTURE_NAME', help='Print authorization info for given api_client_authorizations fixture')
790 parser.add_argument('--num-keep-servers', metavar='int', type=int, default=2, help="Number of keep servers desired")
791 parser.add_argument('--keep-enforce-permissions', action="store_true", help="Enforce keep permissions")
793 args = parser.parse_args()
795 if args.action not in actions:
796 print("Unrecognized action '{}'. Actions are: {}.".
797 format(args.action, actions),
800 if args.action == 'start':
801 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
802 run(leave_running_atexit=True)
803 host = os.environ['ARVADOS_API_HOST']
804 if args.auth is not None:
805 token = auth_token(args.auth)
806 print("export ARVADOS_API_TOKEN={}".format(pipes.quote(token)))
807 print("export ARVADOS_API_HOST={}".format(pipes.quote(host)))
808 print("export ARVADOS_API_HOST_INSECURE=true")
811 elif args.action == 'stop':
812 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
813 elif args.action == 'start_ws':
815 elif args.action == 'stop_ws':
817 elif args.action == 'start_keep':
818 run_keep(enforce_permissions=args.keep_enforce_permissions, num_servers=args.num_keep_servers)
819 elif args.action == 'stop_keep':
820 stop_keep(num_servers=args.num_keep_servers)
821 elif args.action == 'start_keep_proxy':
823 elif args.action == 'stop_keep_proxy':
825 elif args.action == 'start_arv-git-httpd':
827 elif args.action == 'stop_arv-git-httpd':
829 elif args.action == 'start_keep-web':
831 elif args.action == 'stop_keep-web':
833 elif args.action == 'start_nginx':
835 elif args.action == 'stop_nginx':
838 raise Exception("action recognized but not implemented!?")