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 gopaths = os.environ['GOPATH'].split(':')
38 gobins = [os.path.join(path, 'bin') for path in gopaths]
39 os.environ['PATH'] = ':'.join(gobins) + ':' + os.environ['PATH']
41 TEST_TMPDIR = os.path.join(ARVADOS_DIR, 'tmp')
42 if not os.path.exists(TEST_TMPDIR):
47 _cached_db_config = {}
49 def find_server_pid(PID_PATH, wait=10):
53 while (not good_pid) and (now <= timeout):
56 with open(PID_PATH, 'r') as f:
57 server_pid = int(f.read())
58 good_pid = (os.kill(server_pid, 0) is None)
59 except EnvironmentError:
68 def kill_server_pid(pidfile, wait=10, passenger_root=False):
69 # Must re-import modules in order to work during atexit
80 # First try to shut down nicely
81 restore_cwd = os.getcwd()
82 os.chdir(passenger_root)
84 'bundle', 'exec', 'passenger', 'stop', '--pid-file', pidfile])
86 # Use up to half of the +wait+ period waiting for "passenger
87 # stop" to work. If the process hasn't exited by then, start
88 # sending TERM signals.
92 while now <= deadline and server_pid is None:
94 with open(pidfile, 'r') as f:
95 server_pid = int(f.read())
97 # No pidfile = nothing to kill.
99 except ValueError as error:
100 # Pidfile exists, but we can't parse it. Perhaps the
101 # server has created the file but hasn't written its PID
103 print("Parse error reading pidfile {}: {}".format(pidfile, error),
108 while now <= deadline:
110 exited, _ = os.waitpid(server_pid, os.WNOHANG)
114 # already exited, or isn't our child process
118 os.kill(server_pid, signal.SIGTERM)
119 print("Sent SIGTERM to {} ({})".format(server_pid, pidfile),
121 except OSError as error:
122 if error.errno == errno.ESRCH:
123 # Thrown by os.getpgid() or os.kill() if the process
124 # does not exist, i.e., our work here is done.
130 print("Server PID {} ({}) did not exit, giving up after {}s".
131 format(server_pid, pidfile, wait),
134 def find_available_port():
135 """Return an IPv4 port number that is not in use right now.
137 We assume whoever needs to use the returned port is able to reuse
138 a recently used port without waiting for TIME_WAIT (see
139 SO_REUSEADDR / SO_REUSEPORT).
141 Some opportunity for races here, but it's better than choosing
142 something at random and not checking at all. If all of our servers
143 (hey Passenger) knew that listening on port 0 was a thing, the OS
144 would take care of the races, and this wouldn't be needed at all.
147 sock = socket.socket()
148 sock.bind(('0.0.0.0', 0))
149 port = sock.getsockname()[1]
153 def _wait_until_port_listens(port, timeout=10):
154 """Wait for a process to start listening on the given port.
156 If nothing listens on the port within the specified timeout (given
157 in seconds), print a warning on stderr before returning.
160 subprocess.check_output(['which', 'lsof'])
161 except subprocess.CalledProcessError:
162 print("WARNING: No `lsof` -- cannot wait for port to listen. "+
163 "Sleeping 0.5 and hoping for the best.",
167 deadline = time.time() + timeout
168 while time.time() < deadline:
170 subprocess.check_output(
171 ['lsof', '-t', '-i', 'tcp:'+str(port)])
172 except subprocess.CalledProcessError:
177 "WARNING: Nothing is listening on port {} (waited {} seconds).".
178 format(port, timeout),
181 def _fifo2stderr(label):
182 """Create a fifo, and copy it to stderr, prepending label to each line.
184 Return value is the path to the new FIFO.
186 +label+ should contain only alphanumerics: it is also used as part
187 of the FIFO filename.
189 fifo = os.path.join(TEST_TMPDIR, label+'.fifo')
192 except OSError as error:
193 if error.errno != errno.ENOENT:
195 os.mkfifo(fifo, 0700)
197 ['stdbuf', '-i0', '-oL', '-eL', 'sed', '-e', 's/^/['+label+'] /', fifo],
201 def run(leave_running_atexit=False):
202 """Ensure an API server is running, and ARVADOS_API_* env vars have
203 admin credentials for it.
205 If ARVADOS_TEST_API_HOST is set, a parent process has started a
206 test server for us to use: we just need to reset() it using the
209 If a previous call to run() started a new server process, and it
210 is still running, we just need to reset() it to fixture state and
213 If neither of those options work out, we'll really start a new
218 # Delete cached discovery documents.
220 # This will clear cached docs that belong to other processes (like
221 # concurrent test suites) even if they're still running. They should
222 # be able to tolerate that.
223 for fn in glob.glob(os.path.join(arvados.http_cache('discovery'),
224 '*,arvados,v1,rest,*')):
227 pid_file = _pidfile('api')
228 pid_file_ok = find_server_pid(pid_file, 0)
230 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
231 if existing_api_host and pid_file_ok:
232 if existing_api_host == my_api_host:
236 # Fall through to shutdown-and-start case.
239 # Server was provided by parent. Can't recover if it's
243 # Before trying to start up our own server, call stop() to avoid
244 # "Phusion Passenger Standalone is already running on PID 12345".
245 # (If we've gotten this far, ARVADOS_TEST_API_HOST isn't set, so
246 # we know the server is ours to kill.)
249 restore_cwd = os.getcwd()
250 api_src_dir = os.path.join(SERVICES_SRC_DIR, 'api')
251 os.chdir(api_src_dir)
253 # Either we haven't started a server of our own yet, or it has
254 # died, or we have lost our credentials, or something else is
255 # preventing us from calling reset(). Start a new one.
257 if not os.path.exists('tmp'):
260 if not os.path.exists('tmp/api'):
261 os.makedirs('tmp/api')
263 if not os.path.exists('tmp/logs'):
264 os.makedirs('tmp/logs')
266 if not os.path.exists('tmp/self-signed.pem'):
267 # We assume here that either passenger reports its listening
268 # address as https:/0.0.0.0:port/. If it reports "127.0.0.1"
269 # then the certificate won't match the host and reset() will
270 # fail certificate verification. If it reports "localhost",
271 # clients (notably Python SDK's websocket client) might
272 # resolve localhost as ::1 and then fail to connect.
273 subprocess.check_call([
274 'openssl', 'req', '-new', '-x509', '-nodes',
275 '-out', 'tmp/self-signed.pem',
276 '-keyout', 'tmp/self-signed.key',
278 '-subj', '/CN=0.0.0.0'],
281 # Install the git repository fixtures.
282 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
283 gittarball = os.path.join(SERVICES_SRC_DIR, 'api', 'test', 'test.git.tar')
284 if not os.path.isdir(gitdir):
286 subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
288 # The nginx proxy isn't listening here yet, but we need to choose
289 # the wss:// port now so we can write the API server config file.
290 wss_port = find_available_port()
291 _setport('wss', wss_port)
293 port = find_available_port()
294 env = os.environ.copy()
295 env['RAILS_ENV'] = 'test'
296 env['ARVADOS_TEST_WSS_PORT'] = str(wss_port)
297 env.pop('ARVADOS_WEBSOCKETS', None)
298 env.pop('ARVADOS_TEST_API_HOST', None)
299 env.pop('ARVADOS_API_HOST', None)
300 env.pop('ARVADOS_API_HOST_INSECURE', None)
301 env.pop('ARVADOS_API_TOKEN', None)
302 start_msg = subprocess.check_output(
304 'passenger', 'start', '-d', '-p{}'.format(port),
305 '--pid-file', pid_file,
306 '--log-file', os.path.join(os.getcwd(), 'log/test.log'),
308 '--ssl-certificate', 'tmp/self-signed.pem',
309 '--ssl-certificate-key', 'tmp/self-signed.key'],
312 if not leave_running_atexit:
313 atexit.register(kill_server_pid, pid_file, passenger_root=api_src_dir)
315 match = re.search(r'Accessible via: https://(.*?)/', start_msg)
318 "Passenger did not report endpoint: {}".format(start_msg))
319 my_api_host = match.group(1)
320 os.environ['ARVADOS_API_HOST'] = my_api_host
322 # Make sure the server has written its pid file and started
323 # listening on its TCP port
324 find_server_pid(pid_file)
325 _wait_until_port_listens(port)
328 os.chdir(restore_cwd)
331 """Reset the test server to fixture state.
333 This resets the ARVADOS_TEST_API_HOST provided by a parent process
334 if any, otherwise the server started by run().
336 It also resets ARVADOS_* environment vars to point to the test
337 server with admin credentials.
339 existing_api_host = os.environ.get('ARVADOS_TEST_API_HOST', my_api_host)
340 token = auth_token('admin')
341 httpclient = httplib2.Http(ca_certs=os.path.join(
342 SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem'))
344 'https://{}/database/reset'.format(existing_api_host),
346 headers={'Authorization': 'OAuth2 {}'.format(token)})
347 os.environ['ARVADOS_API_HOST_INSECURE'] = 'true'
348 os.environ['ARVADOS_API_HOST'] = existing_api_host
349 os.environ['ARVADOS_API_TOKEN'] = token
351 def stop(force=False):
352 """Stop the API server, if one is running.
354 If force==False, kill it only if we started it ourselves. (This
355 supports the use case where a Python test suite calls run(), but
356 run() just uses the ARVADOS_TEST_API_HOST provided by the parent
357 process, and the test suite cleans up after itself by calling
358 stop(). In this case the test server provided by the parent
359 process should be left alone.)
361 If force==True, kill it even if we didn't start it
362 ourselves. (This supports the use case in __main__, where "run"
363 and "stop" happen in different processes.)
366 if force or my_api_host is not None:
367 kill_server_pid(_pidfile('api'))
371 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
374 port = find_available_port()
375 conf = os.path.join(TEST_TMPDIR, 'ws.yml')
376 with open(conf, 'w') as f:
388 """.format(os.environ['ARVADOS_API_HOST'],
391 _dbconfig('database'),
392 _dbconfig('username'),
393 _dbconfig('password')))
394 logf = open(_fifo2stderr('ws'), 'w')
395 ws = subprocess.Popen(
396 ["ws", "-config", conf],
397 stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
398 with open(_pidfile('ws'), 'w') as f:
400 _wait_until_port_listens(port)
405 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
407 kill_server_pid(_pidfile('ws'))
409 def _start_keep(n, keep_args):
410 keep0 = tempfile.mkdtemp()
411 port = find_available_port()
412 keep_cmd = ["keepstore",
413 "-volume={}".format(keep0),
414 "-listen=:{}".format(port),
415 "-pid="+_pidfile('keep{}'.format(n))]
417 for arg, val in keep_args.iteritems():
418 keep_cmd.append("{}={}".format(arg, val))
420 logf = open(_fifo2stderr('keep{}'.format(n)), 'w')
421 kp0 = subprocess.Popen(
422 keep_cmd, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
424 with open(_pidfile('keep{}'.format(n)), 'w') as f:
425 f.write(str(kp0.pid))
427 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'w') as f:
430 _wait_until_port_listens(port)
434 def run_keep(blob_signing_key=None, enforce_permissions=False, num_servers=2):
435 stop_keep(num_servers)
438 if not blob_signing_key:
439 blob_signing_key = 'zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc'
440 with open(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"), "w") as f:
441 keep_args['-blob-signing-key-file'] = f.name
442 f.write(blob_signing_key)
443 keep_args['-enforce-permissions'] = str(enforce_permissions).lower()
444 with open(os.path.join(TEST_TMPDIR, "keep.data-manager-token-file"), "w") as f:
445 keep_args['-data-manager-token-file'] = f.name
446 f.write(auth_token('data_manager'))
447 keep_args['-never-delete'] = 'false'
451 host=os.environ['ARVADOS_API_HOST'],
452 token=os.environ['ARVADOS_API_TOKEN'],
455 for d in api.keep_services().list(filters=[['service_type','=','disk']]).execute()['items']:
456 api.keep_services().delete(uuid=d['uuid']).execute()
457 for d in api.keep_disks().list().execute()['items']:
458 api.keep_disks().delete(uuid=d['uuid']).execute()
460 for d in range(0, num_servers):
461 port = _start_keep(d, keep_args)
462 svc = api.keep_services().create(body={'keep_service': {
463 'uuid': 'zzzzz-bi6l4-keepdisk{:07d}'.format(d),
464 'service_host': 'localhost',
465 'service_port': port,
466 'service_type': 'disk',
467 'service_ssl_flag': False,
469 api.keep_disks().create(body={
470 'keep_disk': {'keep_service_uuid': svc['uuid'] }
473 # If keepproxy is running, send SIGHUP to make it discover the new
474 # keepstore services.
475 proxypidfile = _pidfile('keepproxy')
476 if os.path.exists(proxypidfile):
478 os.kill(int(open(proxypidfile).read()), signal.SIGHUP)
480 os.remove(proxypidfile)
483 kill_server_pid(_pidfile('keep{}'.format(n)))
484 if os.path.exists("{}/keep{}.volume".format(TEST_TMPDIR, n)):
485 with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'r') as r:
486 shutil.rmtree(r.read(), True)
487 os.unlink("{}/keep{}.volume".format(TEST_TMPDIR, n))
488 if os.path.exists(os.path.join(TEST_TMPDIR, "keep.blob_signing_key")):
489 os.remove(os.path.join(TEST_TMPDIR, "keep.blob_signing_key"))
491 def stop_keep(num_servers=2):
492 for n in range(0, num_servers):
495 def run_keep_proxy():
496 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
500 port = find_available_port()
501 env = os.environ.copy()
502 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
503 logf = open(_fifo2stderr('keepproxy'), 'w')
504 kp = subprocess.Popen(
506 '-pid='+_pidfile('keepproxy'),
507 '-listen=:{}'.format(port)],
508 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
512 host=os.environ['ARVADOS_API_HOST'],
513 token=auth_token('admin'),
515 for d in api.keep_services().list(
516 filters=[['service_type','=','proxy']]).execute()['items']:
517 api.keep_services().delete(uuid=d['uuid']).execute()
518 api.keep_services().create(body={'keep_service': {
519 'service_host': 'localhost',
520 'service_port': port,
521 'service_type': 'proxy',
522 'service_ssl_flag': False,
524 os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(port)
525 _setport('keepproxy', port)
526 _wait_until_port_listens(port)
528 def stop_keep_proxy():
529 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
531 kill_server_pid(_pidfile('keepproxy'))
533 def run_arv_git_httpd():
534 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
538 gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
539 gitport = find_available_port()
540 env = os.environ.copy()
541 env.pop('ARVADOS_API_TOKEN', None)
542 logf = open(_fifo2stderr('arv-git-httpd'), 'w')
543 agh = subprocess.Popen(
545 '-repo-root='+gitdir+'/test',
546 '-address=:'+str(gitport)],
547 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
548 with open(_pidfile('arv-git-httpd'), 'w') as f:
549 f.write(str(agh.pid))
550 _setport('arv-git-httpd', gitport)
551 _wait_until_port_listens(gitport)
553 def stop_arv_git_httpd():
554 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
556 kill_server_pid(_pidfile('arv-git-httpd'))
559 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
563 keepwebport = find_available_port()
564 env = os.environ.copy()
565 env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
566 logf = open(_fifo2stderr('keep-web'), 'w')
567 keepweb = subprocess.Popen(
570 '-attachment-only-host=download:'+str(keepwebport),
571 '-listen=:'+str(keepwebport)],
572 env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
573 with open(_pidfile('keep-web'), 'w') as f:
574 f.write(str(keepweb.pid))
575 _setport('keep-web', keepwebport)
576 _wait_until_port_listens(keepwebport)
579 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
581 kill_server_pid(_pidfile('keep-web'))
584 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
587 nginxconf['KEEPWEBPORT'] = _getport('keep-web')
588 nginxconf['KEEPWEBDLSSLPORT'] = find_available_port()
589 nginxconf['KEEPWEBSSLPORT'] = find_available_port()
590 nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
591 nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
592 nginxconf['GITPORT'] = _getport('arv-git-httpd')
593 nginxconf['GITSSLPORT'] = find_available_port()
594 nginxconf['WSPORT'] = _getport('ws')
595 nginxconf['WSSPORT'] = _getport('wss')
596 nginxconf['SSLCERT'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem')
597 nginxconf['SSLKEY'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.key')
598 nginxconf['ACCESSLOG'] = _fifo2stderr('nginx_access_log')
600 conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
601 conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
602 with open(conffile, 'w') as f:
605 lambda match: str(nginxconf.get(match.group(1))),
606 open(conftemplatefile).read()))
608 env = os.environ.copy()
609 env['PATH'] = env['PATH']+':/sbin:/usr/sbin:/usr/local/sbin'
611 nginx = subprocess.Popen(
613 '-g', 'error_log stderr info;',
614 '-g', 'pid '+_pidfile('nginx')+';',
616 env=env, stdin=open('/dev/null'), stdout=sys.stderr)
617 _setport('keep-web-dl-ssl', nginxconf['KEEPWEBDLSSLPORT'])
618 _setport('keep-web-ssl', nginxconf['KEEPWEBSSLPORT'])
619 _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
620 _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
623 if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
625 kill_server_pid(_pidfile('nginx'))
627 def _pidfile(program):
628 return os.path.join(TEST_TMPDIR, program + '.pid')
630 def _portfile(program):
631 return os.path.join(TEST_TMPDIR, program + '.port')
633 def _setport(program, port):
634 with open(_portfile(program), 'w') as f:
637 # Returns 9 if program is not up.
638 def _getport(program):
640 return int(open(_portfile(program)).read())
645 global _cached_db_config
646 if not _cached_db_config:
647 _cached_db_config = yaml.load(open(os.path.join(
648 SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
649 return _cached_db_config['test'][key]
652 global _cached_config
654 return _cached_config[key]
655 def _load(f, required=True):
656 fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
657 if not required and not os.path.exists(fullpath):
659 return yaml.load(fullpath)
660 cdefault = _load('application.default.yml')
661 csite = _load('application.yml', required=False)
663 for section in [cdefault.get('common',{}), cdefault.get('test',{}),
664 csite.get('common',{}), csite.get('test',{})]:
665 _cached_config.update(section)
666 return _cached_config[key]
669 '''load a fixture yaml file'''
670 with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
674 trim_index = yaml_file.index("# Test Helper trims the rest of the file")
675 yaml_file = yaml_file[0:trim_index]
678 return yaml.load(yaml_file)
680 def auth_token(token_name):
681 return fixture("api_client_authorizations")[token_name]["api_token"]
683 def authorize_with(token_name):
684 '''token_name is the symbolic name of the token from the api_client_authorizations fixture'''
685 arvados.config.settings()["ARVADOS_API_TOKEN"] = auth_token(token_name)
686 arvados.config.settings()["ARVADOS_API_HOST"] = os.environ.get("ARVADOS_API_HOST")
687 arvados.config.settings()["ARVADOS_API_HOST_INSECURE"] = "true"
689 class TestCaseWithServers(unittest.TestCase):
690 """TestCase to start and stop supporting Arvados servers.
692 Define any of MAIN_SERVER, KEEP_SERVER, and/or KEEP_PROXY_SERVER
693 class variables as a dictionary of keyword arguments. If you do,
694 setUpClass will start the corresponding servers by passing these
695 keyword arguments to the run, run_keep, and/or run_keep_server
696 functions, respectively. It will also set Arvados environment
697 variables to point to these servers appropriately. If you don't
698 run a Keep or Keep proxy server, setUpClass will set up a
699 temporary directory for Keep local storage, and set it as
702 tearDownClass will stop any servers started, and restore the
703 original environment.
708 KEEP_PROXY_SERVER = None
709 KEEP_WEB_SERVER = None
712 def _restore_dict(src, dest):
713 for key in dest.keys():
720 cls._orig_environ = os.environ.copy()
721 cls._orig_config = arvados.config.settings().copy()
722 cls._cleanup_funcs = []
723 os.environ.pop('ARVADOS_KEEP_SERVICES', None)
724 os.environ.pop('ARVADOS_EXTERNAL_CLIENT', None)
725 for server_kwargs, start_func, stop_func in (
726 (cls.MAIN_SERVER, run, reset),
727 (cls.WS_SERVER, run_ws, stop_ws),
728 (cls.KEEP_SERVER, run_keep, stop_keep),
729 (cls.KEEP_PROXY_SERVER, run_keep_proxy, stop_keep_proxy),
730 (cls.KEEP_WEB_SERVER, run_keep_web, stop_keep_web)):
731 if server_kwargs is not None:
732 start_func(**server_kwargs)
733 cls._cleanup_funcs.append(stop_func)
734 if (cls.KEEP_SERVER is None) and (cls.KEEP_PROXY_SERVER is None):
735 cls.local_store = tempfile.mkdtemp()
736 os.environ['KEEP_LOCAL_STORE'] = cls.local_store
737 cls._cleanup_funcs.append(
738 lambda: shutil.rmtree(cls.local_store, ignore_errors=True))
740 os.environ.pop('KEEP_LOCAL_STORE', None)
741 arvados.config.initialize()
744 def tearDownClass(cls):
745 for clean_func in cls._cleanup_funcs:
747 cls._restore_dict(cls._orig_environ, os.environ)
748 cls._restore_dict(cls._orig_config, arvados.config.settings())
751 if __name__ == "__main__":
754 'start_ws', 'stop_ws',
755 'start_keep', 'stop_keep',
756 'start_keep_proxy', 'stop_keep_proxy',
757 'start_keep-web', 'stop_keep-web',
758 'start_arv-git-httpd', 'stop_arv-git-httpd',
759 'start_nginx', 'stop_nginx',
761 parser = argparse.ArgumentParser()
762 parser.add_argument('action', type=str, help="one of {}".format(actions))
763 parser.add_argument('--auth', type=str, metavar='FIXTURE_NAME', help='Print authorization info for given api_client_authorizations fixture')
764 parser.add_argument('--num-keep-servers', metavar='int', type=int, default=2, help="Number of keep servers desired")
765 parser.add_argument('--keep-enforce-permissions', action="store_true", help="Enforce keep permissions")
767 args = parser.parse_args()
769 if args.action not in actions:
770 print("Unrecognized action '{}'. Actions are: {}.".
771 format(args.action, actions),
774 if args.action == 'start':
775 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
776 run(leave_running_atexit=True)
777 host = os.environ['ARVADOS_API_HOST']
778 if args.auth is not None:
779 token = auth_token(args.auth)
780 print("export ARVADOS_API_TOKEN={}".format(pipes.quote(token)))
781 print("export ARVADOS_API_HOST={}".format(pipes.quote(host)))
782 print("export ARVADOS_API_HOST_INSECURE=true")
785 elif args.action == 'stop':
786 stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
787 elif args.action == 'start_ws':
789 elif args.action == 'stop_ws':
791 elif args.action == 'start_keep':
792 run_keep(enforce_permissions=args.keep_enforce_permissions, num_servers=args.num_keep_servers)
793 elif args.action == 'stop_keep':
794 stop_keep(num_servers=args.num_keep_servers)
795 elif args.action == 'start_keep_proxy':
797 elif args.action == 'stop_keep_proxy':
799 elif args.action == 'start_arv-git-httpd':
801 elif args.action == 'stop_arv-git-httpd':
803 elif args.action == 'start_keep-web':
805 elif args.action == 'stop_keep-web':
807 elif args.action == 'start_nginx':
809 elif args.action == 'stop_nginx':
812 raise Exception("action recognized but not implemented!?")