3 from __future__ import print_function
4 from __future__ import division
5 from builtins import str
6 from builtins import range
7 from past.utils import old_div
28 MY_DIRNAME = os.path.dirname(os.path.realpath(__file__))
29 if __name__ == '__main__' and os.path.exists(
30 os.path.join(MY_DIRNAME, '..', 'arvados', '__init__.py')):
31 # We're being launched to support another test suite.
32 # Add the Python SDK source to the library path.
33 sys.path.insert(1, os.path.dirname(MY_DIRNAME))
38 ARVADOS_DIR = os.path.realpath(os.path.join(MY_DIRNAME, '../../..'))
39 SERVICES_SRC_DIR = os.path.join(ARVADOS_DIR, 'services')
40 if 'GOPATH' in os.environ:
41 # Add all GOPATH bin dirs to PATH -- but insert them after the
42 # ruby gems bin dir, to ensure "bundle" runs the Ruby bundler
43 # command, not the golang.org/x/tools/cmd/bundle command.
44 gopaths = os.environ['GOPATH'].split(':')
45 addbins = [os.path.join(path, 'bin') for path in gopaths]
47 for path in os.environ['PATH'].split(':'):
49 if os.path.exists(os.path.join(path, 'bundle')):
53 os.environ['PATH'] = ':'.join(newbins)
55 TEST_TMPDIR = os.path.join(ARVADOS_DIR, 'tmp')
56 if not os.path.exists(TEST_TMPDIR):
61 _cached_db_config = {}
63 def find_server_pid(PID_PATH, wait=10):
67 while (not good_pid) and (now <= timeout):
70 with open(PID_PATH, 'r') as f:
71 server_pid = int(f.read())
72 good_pid = (os.kill(server_pid, 0) is None)
73 except EnvironmentError:
82 def kill_server_pid(pidfile, wait=10, passenger_root=False):
83 # Must re-import modules in order to work during atexit
94 # First try to shut down nicely
95 restore_cwd = os.getcwd()
96 os.chdir(passenger_root)
98 'bundle', 'exec', 'passenger', 'stop', '--pid-file', pidfile])
100 # Use up to half of the +wait+ period waiting for "passenger
101 # stop" to work. If the process hasn't exited by then, start
102 # sending TERM signals.
103 startTERM += old_div(wait,2)
106 while now <= deadline and server_pid is None:
108 with open(pidfile, 'r') as f:
109 server_pid = int(f.read())
111 # No pidfile = nothing to kill.
113 except ValueError as error:
114 # Pidfile exists, but we can't parse it. Perhaps the
115 # server has created the file but hasn't written its PID
117 print("Parse error reading pidfile {}: {}".format(pidfile, error),
122 while now <= deadline:
124 exited, _ = os.waitpid(server_pid, os.WNOHANG)
126 _remove_pidfile(pidfile)
129 # already exited, or isn't our child process
133 os.kill(server_pid, signal.SIGTERM)
134 print("Sent SIGTERM to {} ({})".format(server_pid, pidfile),
136 except OSError as error:
137 if error.errno == errno.ESRCH:
138 # Thrown by os.getpgid() or os.kill() if the process
139 # does not exist, i.e., our work here is done.
140 _remove_pidfile(pidfile)
146 print("Server PID {} ({}) did not exit, giving up after {}s".
147 format(server_pid, pidfile, wait),
150 def _remove_pidfile(pidfile):
154 if os.path.lexists(pidfile):
157 def find_available_port():
158 """Return an IPv4 port number that is not in use right now.
160 We assume whoever needs to use the returned port is able to reuse
161 a recently used port without waiting for TIME_WAIT (see
162 SO_REUSEADDR / SO_REUSEPORT).
164 Some opportunity for races here, but it's better than choosing
165 something at random and not checking at all. If all of our servers
166 (hey Passenger) knew that listening on port 0 was a thing, the OS
167 would take care of the races, and this wouldn't be needed at all.
170 sock = socket.socket()
171 sock.bind(('0.0.0.0', 0))
172 port = sock.getsockname()[1]
176 def _wait_until_port_listens(port, timeout=10):
177 """Wait for a process to start listening on the given port.
179 If nothing listens on the port within the specified timeout (given
180 in seconds), print a warning on stderr before returning.
183 subprocess.check_output(['which', 'lsof'])
184 except subprocess.CalledProcessError:
185 print("WARNING: No `lsof` -- cannot wait for port to listen. "+
186 "Sleeping 0.5 and hoping for the best.",
190 deadline = time.time() + timeout
191 while time.time() < deadline:
193 subprocess.check_output(
194 ['lsof', '-t', '-i', 'tcp:'+str(port)])
195 except subprocess.CalledProcessError:
200 "WARNING: Nothing is listening on port {} (waited {} seconds).".
201 format(port, timeout),
204 def _fifo2stderr(label):
205 """Create a fifo, and copy it to stderr, prepending label to each line.
207 Return value is the path to the new FIFO.
209 +label+ should contain only alphanumerics: it is also used as part
210 of the FIFO filename.
212 fifo = os.path.join(TEST_TMPDIR, label+'.fifo')
215 except OSError as error:
216 if error.errno != errno.ENOENT:
218 os.mkfifo(fifo, 0o700)
220 ['stdbuf', '-i0', '-oL', '-eL', 'sed', '-e', 's/^/['+label+'] /', fifo],
224 def run(leave_running_atexit=False):
225 """Ensure an API server is running, and ARVADOS_API_* env vars have
226 admin credentials for it.
228 If ARVADOS_TEST_API_HOST is set, a parent process has started a
229 test server for us to use: we just need to reset() it using the
232 If a previous call to run() started a new server process, and it
233 is still running, we just need to reset() it to fixture state and
236 If neither of those options work out, we'll really start a new
241 # Delete cached discovery documents.
243 # This will clear cached docs that belong to other processes (like
244 # concurrent test suites) even if they're still running. They should
245 # be able to tolerate that.
246 for fn in glob.glob(os.path.join(
247 str(arvados.http_cache('discovery')),
248 '*,arvados,v1,rest,*')):
251 pid_file = _pidfile('api')
252 pid_file_ok = find_server_pid(pid_file, 0)
254 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
255 if existing_api_host and pid_file_ok:
256 if existing_api_host == my_api_host:
260 # Fall through to shutdown-and-start case.
263 # Server was provided by parent. Can't recover if it's
267 # Before trying to start up our own server, call stop() to avoid
268 # "Phusion Passenger Standalone is already running on PID 12345".
269 # (If we've gotten this far, ARVADOS_TEST_API_HOST isn't set, so
270 # we know the server is ours to kill.)
273 restore_cwd = os.getcwd()
274 api_src_dir = os.path.join(SERVICES_SRC_DIR, 'api')
275 os.chdir(api_src_dir)
277 # Either we haven't started a server of our own yet, or it has
278 # died, or we have lost our credentials, or something else is
279 # preventing us from calling reset(). Start a new one.
281 if not os.path.exists('tmp'):
284 if not os.path.exists('tmp/api'):
285 os.makedirs('tmp/api')
287 if not os.path.exists('tmp/logs'):
288 os.makedirs('tmp/logs')
290 if not os.path.exists('tmp/self-signed.pem'):
291 # We assume here that either passenger reports its listening
292 # address as https:/0.0.0.0:port/. If it reports "127.0.0.1"
293 # then the certificate won't match the host and reset() will
294 # fail certificate verification. If it reports "localhost",
295 # clients (notably Python SDK's websocket client) might
296 # resolve localhost as ::1 and then fail to connect.
297 subprocess.check_call([
298 'openssl', 'req', '-new', '-x509', '-nodes',
299 '-out', 'tmp/self-signed.pem',
300 '-keyout', 'tmp/self-signed.key',
302 '-subj', '/CN=0.0.0.0'],
305 # Install the git repository fixtures.
306 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
307 gittarball = os.path.join(SERVICES_SRC_DIR, 'api', 'test', 'test.git.tar')
308 if not os.path.isdir(gitdir):
310 subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
312 # The nginx proxy isn't listening here yet, but we need to choose
313 # the wss:// port now so we can write the API server config file.
314 wss_port = find_available_port()
315 _setport('wss', wss_port)
317 port = find_available_port()
318 env = os.environ.copy()
319 env['RAILS_ENV'] = 'test'
320 env['ARVADOS_TEST_WSS_PORT'] = str(wss_port)
321 if env.get('ARVADOS_TEST_EXPERIMENTAL_WS'):
322 env.pop('ARVADOS_WEBSOCKETS', None)
324 env['ARVADOS_WEBSOCKETS'] = 'yes'
325 env.pop('ARVADOS_TEST_API_HOST', None)
326 env.pop('ARVADOS_API_HOST', None)
327 env.pop('ARVADOS_API_HOST_INSECURE', None)
328 env.pop('ARVADOS_API_TOKEN', None)
329 start_msg = subprocess.check_output(
331 'passenger', 'start', '-d', '-p{}'.format(port),
332 '--pid-file', pid_file,
333 '--log-file', os.path.join(os.getcwd(), 'log/test.log'),
335 '--ssl-certificate', 'tmp/self-signed.pem',
336 '--ssl-certificate-key', 'tmp/self-signed.key'],
339 if not leave_running_atexit:
340 atexit.register(kill_server_pid, pid_file, passenger_root=api_src_dir)
342 match = re.search(r'Accessible via: https://(.*?)/', start_msg)
345 "Passenger did not report endpoint: {}".format(start_msg))
346 my_api_host = match.group(1)
347 os.environ['ARVADOS_API_HOST'] = my_api_host
349 # Make sure the server has written its pid file and started
350 # listening on its TCP port
351 find_server_pid(pid_file)
352 _wait_until_port_listens(port)
355 os.chdir(restore_cwd)
358 """Reset the test server to fixture state.
360 This resets the ARVADOS_TEST_API_HOST provided by a parent process
361 if any, otherwise the server started by run().
363 It also resets ARVADOS_* environment vars to point to the test
364 server with admin credentials.
366 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
367 token = auth_token('admin')
368 httpclient = httplib2.Http(ca_certs=os.path.join(
369 SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem'))
371 'https://{}/database/reset'.format(existing_api_host),
373 headers={'Authorization': 'OAuth2 {}'.format(token)})
374 os.environ['ARVADOS_API_HOST_INSECURE'] = 'true'
375 os.environ['ARVADOS_API_HOST'] = existing_api_host
376 os.environ['ARVADOS_API_TOKEN'] = token
378 def stop(force=False):
379 """Stop the API server, if one is running.
381 If force==False, kill it only if we started it ourselves. (This
382 supports the use case where a Python test suite calls run(), but
383 run() just uses the ARVADOS_TEST_API_HOST provided by the parent
384 process, and the test suite cleans up after itself by calling
385 stop(). In this case the test server provided by the parent
386 process should be left alone.)
388 If force==True, kill it even if we didn't start it
389 ourselves. (This supports the use case in __main__, where "run"
390 and "stop" happen in different processes.)
393 if force or my_api_host is not None:
394 kill_server_pid(_pidfile('api'))
398 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
401 port = find_available_port()
402 conf = os.path.join(TEST_TMPDIR, 'ws.yml')
403 with open(conf, 'w') as f:
416 """.format(os.environ['ARVADOS_API_HOST'],
418 ('info' if os.environ.get('ARVADOS_DEBUG', '') in ['','0'] else 'debug'),
420 _dbconfig('database'),
421 _dbconfig('username'),
422 _dbconfig('password')))
423 logf = open(_fifo2stderr('ws'), 'w')
424 ws = subprocess.Popen(
425 ["ws", "-config", conf],
426 stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
427 with open(_pidfile('ws'), 'w') as f:
429 _wait_until_port_listens(port)
434 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
436 kill_server_pid(_pidfile('ws'))
438 def _start_keep(n, keep_args):
439 keep0 = tempfile.mkdtemp()
440 port = find_available_port()
441 keep_cmd = ["keepstore",
442 "-volume={}".format(keep0),
443 "-listen=:{}".format(port),
444 "-pid="+_pidfile('keep{}'.format(n))]
446 for arg, val in keep_args.items():
447 keep_cmd.append("{}={}".format(arg, val))
449 logf = open(_fifo2stderr('keep{}'.format(n)), 'w')
450 kp0 = subprocess.Popen(
451 keep_cmd, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
453 with open(_pidfile('keep{}'.format(n)), 'w') as f:
454 f.write(str(kp0.pid))
456 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'w') as f:
459 _wait_until_port_listens(port)
463 def run_keep(blob_signing_key=None, enforce_permissions=False, num_servers=2):
464 stop_keep(num_servers)
467 if not blob_signing_key:
468 blob_signing_key = 'zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc'
469 with open(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"), "w") as f:
470 keep_args['-blob-signing-key-file'] = f.name
471 f.write(blob_signing_key)
472 keep_args['-enforce-permissions'] = str(enforce_permissions).lower()
473 with open(os.path.join(TEST_TMPDIR, "keep.data-manager-token-file"), "w") as f:
474 keep_args['-data-manager-token-file'] = f.name
475 f.write(auth_token('data_manager'))
476 keep_args['-never-delete'] = 'false'
480 host=os.environ['ARVADOS_API_HOST'],
481 token=os.environ['ARVADOS_API_TOKEN'],
484 for d in api.keep_services().list(filters=[['service_type','=','disk']]).execute()['items']:
485 api.keep_services().delete(uuid=d['uuid']).execute()
486 for d in api.keep_disks().list().execute()['items']:
487 api.keep_disks().delete(uuid=d['uuid']).execute()
489 for d in range(0, num_servers):
490 port = _start_keep(d, keep_args)
491 svc = api.keep_services().create(body={'keep_service': {
492 'uuid': 'zzzzz-bi6l4-keepdisk{:07d}'.format(d),
493 'service_host': 'localhost',
494 'service_port': port,
495 'service_type': 'disk',
496 'service_ssl_flag': False,
498 api.keep_disks().create(body={
499 'keep_disk': {'keep_service_uuid': svc['uuid'] }
502 # If keepproxy is running, send SIGHUP to make it discover the new
503 # keepstore services.
504 proxypidfile = _pidfile('keepproxy')
505 if os.path.exists(proxypidfile):
507 os.kill(int(open(proxypidfile).read()), signal.SIGHUP)
509 os.remove(proxypidfile)
512 kill_server_pid(_pidfile('keep{}'.format(n)))
513 if os.path.exists("{}/keep{}.volume".format(TEST_TMPDIR, n)):
514 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'r') as r:
515 shutil.rmtree(r.read(), True)
516 os.unlink("{}/keep{}.volume".format(TEST_TMPDIR, n))
517 if os.path.exists(os.path.join(TEST_TMPDIR, "keep.blob_signing_key")):
518 os.remove(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"))
520 def stop_keep(num_servers=2):
521 for n in range(0, num_servers):
524 def run_keep_proxy():
525 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
529 port = find_available_port()
530 env = os.environ.copy()
531 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
532 logf = open(_fifo2stderr('keepproxy'), 'w')
533 kp = subprocess.Popen(
535 '-pid='+_pidfile('keepproxy'),
536 '-listen=:{}'.format(port)],
537 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
541 host=os.environ['ARVADOS_API_HOST'],
542 token=auth_token('admin'),
544 for d in api.keep_services().list(
545 filters=[['service_type','=','proxy']]).execute()['items']:
546 api.keep_services().delete(uuid=d['uuid']).execute()
547 api.keep_services().create(body={'keep_service': {
548 'service_host': 'localhost',
549 'service_port': port,
550 'service_type': 'proxy',
551 'service_ssl_flag': False,
553 os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(port)
554 _setport('keepproxy', port)
555 _wait_until_port_listens(port)
557 def stop_keep_proxy():
558 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
560 kill_server_pid(_pidfile('keepproxy'))
562 def run_arv_git_httpd():
563 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
567 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
568 gitport = find_available_port()
569 env = os.environ.copy()
570 env.pop('ARVADOS_API_TOKEN', None)
571 logf = open(_fifo2stderr('arv-git-httpd'), 'w')
572 agh = subprocess.Popen(
574 '-repo-root='+gitdir+'/test',
575 '-address=:'+str(gitport)],
576 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
577 with open(_pidfile('arv-git-httpd'), 'w') as f:
578 f.write(str(agh.pid))
579 _setport('arv-git-httpd', gitport)
580 _wait_until_port_listens(gitport)
582 def stop_arv_git_httpd():
583 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
585 kill_server_pid(_pidfile('arv-git-httpd'))
588 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
592 keepwebport = find_available_port()
593 env = os.environ.copy()
594 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
595 logf = open(_fifo2stderr('keep-web'), 'w')
596 keepweb = subprocess.Popen(
599 '-attachment-only-host=download:'+str(keepwebport),
600 '-listen=:'+str(keepwebport)],
601 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
602 with open(_pidfile('keep-web'), 'w') as f:
603 f.write(str(keepweb.pid))
604 _setport('keep-web', keepwebport)
605 _wait_until_port_listens(keepwebport)
608 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
610 kill_server_pid(_pidfile('keep-web'))
613 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
617 nginxconf['KEEPWEBPORT'] = _getport('keep-web')
618 nginxconf['KEEPWEBDLSSLPORT'] = find_available_port()
619 nginxconf['KEEPWEBSSLPORT'] = find_available_port()
620 nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
621 nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
622 nginxconf['GITPORT'] = _getport('arv-git-httpd')
623 nginxconf['GITSSLPORT'] = find_available_port()
624 nginxconf['WSPORT'] = _getport('ws')
625 nginxconf['WSSPORT'] = _getport('wss')
626 nginxconf['SSLCERT'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem')
627 nginxconf['SSLKEY'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.key')
628 nginxconf['ACCESSLOG'] = _fifo2stderr('nginx_access_log')
630 conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
631 conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
632 with open(conffile, 'w') as f:
635 lambda match: str(nginxconf.get(match.group(1))),
636 open(conftemplatefile).read()))
638 env = os.environ.copy()
639 env['PATH'] = env['PATH']+':/sbin:/usr/sbin:/usr/local/sbin'
641 nginx = subprocess.Popen(
643 '-g', 'error_log stderr info;',
644 '-g', 'pid '+_pidfile('nginx')+';',
646 env=env, stdin=open('/dev/null'), stdout=sys.stderr)
647 _setport('keep-web-dl-ssl', nginxconf['KEEPWEBDLSSLPORT'])
648 _setport('keep-web-ssl', nginxconf['KEEPWEBSSLPORT'])
649 _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
650 _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
653 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
655 kill_server_pid(_pidfile('nginx'))
657 def _pidfile(program):
658 return os.path.join(TEST_TMPDIR, program + '.pid')
660 def _portfile(program):
661 return os.path.join(TEST_TMPDIR, program + '.port')
663 def _setport(program, port):
664 with open(_portfile(program), 'w') as f:
667 # Returns 9 if program is not up.
668 def _getport(program):
670 return int(open(_portfile(program)).read())
675 global _cached_db_config
676 if not _cached_db_config:
677 _cached_db_config = yaml.load(open(os.path.join(
678 SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
679 return _cached_db_config['test'][key]
682 global _cached_config
684 return _cached_config[key]
685 def _load(f, required=True):
686 fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
687 if not required and not os.path.exists(fullpath):
689 return yaml.load(fullpath)
690 cdefault = _load('application.default.yml')
691 csite = _load('application.yml', required=False)
693 for section in [cdefault.get('common',{}), cdefault.get('test',{}),
694 csite.get('common',{}), csite.get('test',{})]:
695 _cached_config.update(section)
696 return _cached_config[key]
699 '''load a fixture yaml file'''
700 with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
704 trim_index = yaml_file.index("# Test Helper trims the rest of the file")
705 yaml_file = yaml_file[0:trim_index]
708 return yaml.load(yaml_file)
710 def auth_token(token_name):
711 return fixture("api_client_authorizations")[token_name]["api_token"]
713 def authorize_with(token_name):
714 '''token_name is the symbolic name of the token from the api_client_authorizations fixture'''
715 arvados.config.settings()["ARVADOS_API_TOKEN"] = auth_token(token_name)
716 arvados.config.settings()["ARVADOS_API_HOST"] = os.environ.get("ARVADOS_API_HOST")
717 arvados.config.settings()["ARVADOS_API_HOST_INSECURE"] = "true"
719 class TestCaseWithServers(unittest.TestCase):
720 """TestCase to start and stop supporting Arvados servers.
722 Define any of MAIN_SERVER, KEEP_SERVER, and/or KEEP_PROXY_SERVER
723 class variables as a dictionary of keyword arguments. If you do,
724 setUpClass will start the corresponding servers by passing these
725 keyword arguments to the run, run_keep, and/or run_keep_server
726 functions, respectively. It will also set Arvados environment
727 variables to point to these servers appropriately. If you don't
728 run a Keep or Keep proxy server, setUpClass will set up a
729 temporary directory for Keep local storage, and set it as
732 tearDownClass will stop any servers started, and restore the
733 original environment.
738 KEEP_PROXY_SERVER = None
739 KEEP_WEB_SERVER = None
742 def _restore_dict(src, dest):
743 for key in list(dest.keys()):
750 cls._orig_environ = os.environ.copy()
751 cls._orig_config = arvados.config.settings().copy()
752 cls._cleanup_funcs = []
753 os.environ.pop('ARVADOS_KEEP_SERVICES', None)
754 os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
755 for server_kwargs, start_func, stop_func in (
756 (cls.MAIN_SERVER, run, reset),
757 (cls.WS_SERVER, run_ws, stop_ws),
758 (cls.KEEP_SERVER, run_keep, stop_keep),
759 (cls.KEEP_PROXY_SERVER, run_keep_proxy, stop_keep_proxy),
760 (cls.KEEP_WEB_SERVER, run_keep_web, stop_keep_web)):
761 if server_kwargs is not None:
762 start_func(**server_kwargs)
763 cls._cleanup_funcs.append(stop_func)
764 if (cls.KEEP_SERVER is None) and (cls.KEEP_PROXY_SERVER is None):
765 cls.local_store = tempfile.mkdtemp()
766 os.environ['KEEP_LOCAL_STORE'] = cls.local_store
767 cls._cleanup_funcs.append(
768 lambda: shutil.rmtree(cls.local_store, ignore_errors=True))
770 os.environ.pop('KEEP_LOCAL_STORE', None)
771 arvados.config.initialize()
774 def tearDownClass(cls):
775 for clean_func in cls._cleanup_funcs:
777 cls._restore_dict(cls._orig_environ, os.environ)
778 cls._restore_dict(cls._orig_config, arvados.config.settings())
781 if __name__ == "__main__":
784 'start_ws', 'stop_ws',
785 'start_keep', 'stop_keep',
786 'start_keep_proxy', 'stop_keep_proxy',
787 'start_keep-web', 'stop_keep-web',
788 'start_arv-git-httpd', 'stop_arv-git-httpd',
789 'start_nginx', 'stop_nginx',
791 parser = argparse.ArgumentParser()
792 parser.add_argument('action', type=str, help="one of {}".format(actions))
793 parser.add_argument('--auth', type=str, metavar='FIXTURE_NAME', help='Print authorization info for given api_client_authorizations fixture')
794 parser.add_argument('--num-keep-servers', metavar='int', type=int, default=2, help="Number of keep servers desired")
795 parser.add_argument('--keep-enforce-permissions', action="store_true", help="Enforce keep permissions")
797 args = parser.parse_args()
799 if args.action not in actions:
800 print("Unrecognized action '{}'. Actions are: {}.".
801 format(args.action, actions),
804 if args.action == 'start':
805 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
806 run(leave_running_atexit=True)
807 host = os.environ['ARVADOS_API_HOST']
808 if args.auth is not None:
809 token = auth_token(args.auth)
810 print("export ARVADOS_API_TOKEN={}".format(pipes.quote(token)))
811 print("export ARVADOS_API_HOST={}".format(pipes.quote(host)))
812 print("export ARVADOS_API_HOST_INSECURE=true")
815 elif args.action == 'stop':
816 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
817 elif args.action == 'start_ws':
819 elif args.action == 'stop_ws':
821 elif args.action == 'start_keep':
822 run_keep(enforce_permissions=args.keep_enforce_permissions, num_servers=args.num_keep_servers)
823 elif args.action == 'stop_keep':
824 stop_keep(num_servers=args.num_keep_servers)
825 elif args.action == 'start_keep_proxy':
827 elif args.action == 'stop_keep_proxy':
829 elif args.action == 'start_arv-git-httpd':
831 elif args.action == 'stop_arv-git-httpd':
833 elif args.action == 'start_keep-web':
835 elif args.action == 'stop_keep-web':
837 elif args.action == 'start_nginx':
839 elif args.action == 'stop_nginx':
842 raise Exception("action recognized but not implemented!?")