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 and/or keep-web is running, send SIGHUP to make
497 # them discover the new keepstore services.
498 for svc in ('keepproxy', 'keep-web'):
499 pidfile = _pidfile('keepproxy')
500 if os.path.exists(pidfile):
502 os.kill(int(open(pidfile).read()), signal.SIGHUP)
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 list(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!?")