import unittest
import yaml
+try:
+ from urllib.parse import urlparse
+except ImportError:
+ from urlparse import urlparse
+
MY_DIRNAME = os.path.dirname(os.path.realpath(__file__))
if __name__ == '__main__' and os.path.exists(
os.path.join(MY_DIRNAME, '..', 'arvados', '__init__.py')):
sock.close()
return port
-def _wait_until_port_listens(port, timeout=10):
+def _wait_until_port_listens(port, timeout=10, warn=True):
"""Wait for a process to start listening on the given port.
If nothing listens on the port within the specified timeout (given
in seconds), print a warning on stderr before returning.
"""
try:
- subprocess.check_output(['which', 'lsof'])
+ subprocess.check_output(['which', 'netstat'])
except subprocess.CalledProcessError:
- print("WARNING: No `lsof` -- cannot wait for port to listen. "+
+ print("WARNING: No `netstat` -- cannot wait for port to listen. "+
"Sleeping 0.5 and hoping for the best.",
file=sys.stderr)
time.sleep(0.5)
return
deadline = time.time() + timeout
while time.time() < deadline:
- try:
- subprocess.check_output(
- ['lsof', '-t', '-i', 'tcp:'+str(port)])
- except subprocess.CalledProcessError:
- time.sleep(0.1)
- continue
- return
- print(
- "WARNING: Nothing is listening on port {} (waited {} seconds).".
- format(port, timeout),
- file=sys.stderr)
+ if re.search(r'\ntcp.*:'+str(port)+' .* LISTEN *\n', subprocess.check_output(['netstat', '-Wln']).decode()):
+ return True
+ time.sleep(0.1)
+ if warn:
+ print(
+ "WARNING: Nothing is listening on port {} (waited {} seconds).".
+ format(port, timeout),
+ file=sys.stderr)
+ return False
def _logfilename(label):
"""Set up a labelled log file, and return a path to write logs to.
os.makedirs(gitdir)
subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
- # The nginx proxy isn't listening here yet, but we need to choose
- # the wss:// port now so we can write the API server config file.
- wss_port = find_available_port()
- _setport('wss', wss_port)
-
- port = find_available_port()
+ port = internal_port_from_config("RailsAPI")
env = os.environ.copy()
env['RAILS_ENV'] = 'test'
- env['ARVADOS_TEST_WSS_PORT'] = str(wss_port)
env.pop('ARVADOS_WEBSOCKETS', None)
env.pop('ARVADOS_TEST_API_HOST', None)
env.pop('ARVADOS_API_HOST', None)
httpclient.request(
'https://{}/database/reset'.format(existing_api_host),
'POST',
- headers={'Authorization': 'OAuth2 {}'.format(token)})
+ headers={'Authorization': 'OAuth2 {}'.format(token), 'Connection':'close'})
+
os.environ['ARVADOS_API_HOST_INSECURE'] = 'true'
- os.environ['ARVADOS_API_HOST'] = existing_api_host
os.environ['ARVADOS_API_TOKEN'] = token
+ os.environ['ARVADOS_API_HOST'] = existing_api_host
def stop(force=False):
"""Stop the API server, if one is running.
kill_server_pid(_pidfile('api'))
my_api_host = None
+def get_config():
+ with open(os.environ["ARVADOS_CONFIG"]) as f:
+ return yaml.safe_load(f)
+
+def internal_port_from_config(service):
+ return int(urlparse(
+ list(get_config()["Clusters"]["zzzzz"]["Services"][service]["InternalURLs"].keys())[0]).
+ netloc.split(":")[1])
+
+def external_port_from_config(service):
+ return int(urlparse(get_config()["Clusters"]["zzzzz"]["Services"][service]["ExternalURL"]).netloc.split(":")[1])
+
def run_controller():
if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
return
stop_controller()
- rails_api_port = int(string.split(os.environ.get('ARVADOS_TEST_API_HOST', my_api_host), ':')[-1])
- port = find_available_port()
- conf = os.path.join(TEST_TMPDIR, 'arvados.yml')
- with open(conf, 'w') as f:
- f.write("""
-Clusters:
- zzzzz:
- NodeProfiles:
- "*":
- "arvados-controller":
- Listen: ":{}"
- "arvados-api-server":
- Listen: ":{}"
- TLS: true
- """.format(port, rails_api_port))
logf = open(_logfilename('controller'), 'a')
+ port = internal_port_from_config("Controller")
controller = subprocess.Popen(
- ["arvados-server", "controller", "-config", conf],
+ ["arvados-server", "controller"],
stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
with open(_pidfile('controller'), 'w') as f:
f.write(str(controller.pid))
_wait_until_port_listens(port)
- _setport('controller', port)
return port
def stop_controller():
if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
return
stop_ws()
- port = find_available_port()
- conf = os.path.join(TEST_TMPDIR, 'ws.yml')
- with open(conf, 'w') as f:
- f.write("""
-Client:
- APIHost: {}
- Insecure: true
-Listen: :{}
-LogLevel: {}
-Postgres:
- host: {}
- dbname: {}
- user: {}
- password: {}
- sslmode: require
- """.format(os.environ['ARVADOS_API_HOST'],
- port,
- ('info' if os.environ.get('ARVADOS_DEBUG', '') in ['','0'] else 'debug'),
- _dbconfig('host'),
- _dbconfig('database'),
- _dbconfig('username'),
- _dbconfig('password')))
+ port = internal_port_from_config("Websocket")
logf = open(_logfilename('ws'), 'a')
- ws = subprocess.Popen(
- ["ws", "-config", conf],
+ ws = subprocess.Popen(["ws"],
stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
with open(_pidfile('ws'), 'w') as f:
f.write(str(ws.pid))
_wait_until_port_listens(port)
- _setport('ws', port)
return port
def stop_ws():
for arg, val in keep_args.items():
keep_cmd.append("{}={}".format(arg, val))
- logf = open(_logfilename('keep{}'.format(n)), 'a')
- kp0 = subprocess.Popen(
- keep_cmd, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
+ with open(_logfilename('keep{}'.format(n)), 'a') as logf:
+ with open('/dev/null') as _stdin:
+ kp0 = subprocess.Popen(
+ keep_cmd, stdin=_stdin, stdout=logf, stderr=logf, close_fds=True)
with open(_pidfile('keep{}'.format(n)), 'w') as f:
f.write(str(kp0.pid))
pidfile = _pidfile('keepproxy')
if os.path.exists(pidfile):
try:
- os.kill(int(open(pidfile).read()), signal.SIGHUP)
+ with open(pidfile) as pid:
+ os.kill(int(pid.read()), signal.SIGHUP)
except OSError:
os.remove(pidfile)
def run_keep_proxy():
if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
+ os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(internal_port_from_config('Keepproxy'))
return
stop_keep_proxy()
- port = find_available_port()
+ port = internal_port_from_config("Keepproxy")
env = os.environ.copy()
env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
logf = open(_logfilename('keepproxy'), 'a')
'-listen=:{}'.format(port)],
env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf, close_fds=True)
+ print("Using API %s token %s" % (os.environ['ARVADOS_API_HOST'], auth_token('admin')), file=sys.stdout)
api = arvados.api(
version='v1',
host=os.environ['ARVADOS_API_HOST'],
'service_ssl_flag': False,
}}).execute()
os.environ["ARVADOS_KEEP_SERVICES"] = "http://localhost:{}".format(port)
- _setport('keepproxy', port)
_wait_until_port_listens(port)
def stop_keep_proxy():
stop_arv_git_httpd()
gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
- gitport = find_available_port()
+ gitport = internal_port_from_config("GitHTTP")
env = os.environ.copy()
env.pop('ARVADOS_API_TOKEN', None)
logf = open(_logfilename('arv-git-httpd'), 'a')
agh = subprocess.Popen(
['arv-git-httpd',
'-repo-root='+gitdir+'/test',
+ '-management-token=e687950a23c3a9bceec28c6223a06c79',
'-address=:'+str(gitport)],
env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
with open(_pidfile('arv-git-httpd'), 'w') as f:
f.write(str(agh.pid))
- _setport('arv-git-httpd', gitport)
_wait_until_port_listens(gitport)
def stop_arv_git_httpd():
return
stop_keep_web()
- keepwebport = find_available_port()
+ keepwebport = internal_port_from_config("WebDAV")
env = os.environ.copy()
env['ARVADOS_API_TOKEN'] = auth_token('anonymous')
logf = open(_logfilename('keep-web'), 'a')
keepweb = subprocess.Popen(
['keep-web',
'-allow-anonymous',
- '-attachment-only-host=download:'+str(keepwebport),
+ '-attachment-only-host=download',
+ '-management-token=e687950a23c3a9bceec28c6223a06c79',
'-listen=:'+str(keepwebport)],
env=env, stdin=open('/dev/null'), stdout=logf, stderr=logf)
with open(_pidfile('keep-web'), 'w') as f:
f.write(str(keepweb.pid))
- _setport('keep-web', keepwebport)
_wait_until_port_listens(keepwebport)
def stop_keep_web():
return
stop_nginx()
nginxconf = {}
- nginxconf['CONTROLLERPORT'] = _getport('controller')
- nginxconf['CONTROLLERSSLPORT'] = find_available_port()
- nginxconf['KEEPWEBPORT'] = _getport('keep-web')
- nginxconf['KEEPWEBDLSSLPORT'] = find_available_port()
- nginxconf['KEEPWEBSSLPORT'] = find_available_port()
- nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
- nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
- nginxconf['GITPORT'] = _getport('arv-git-httpd')
- nginxconf['GITSSLPORT'] = find_available_port()
- nginxconf['WSPORT'] = _getport('ws')
- nginxconf['WSSPORT'] = _getport('wss')
+ nginxconf['CONTROLLERPORT'] = internal_port_from_config("Controller")
+ nginxconf['CONTROLLERSSLPORT'] = external_port_from_config("Controller")
+ nginxconf['KEEPWEBPORT'] = internal_port_from_config("WebDAV")
+ nginxconf['KEEPWEBDLSSLPORT'] = external_port_from_config("WebDAVDownload")
+ nginxconf['KEEPWEBSSLPORT'] = external_port_from_config("WebDAV")
+ nginxconf['KEEPPROXYPORT'] = internal_port_from_config("Keepproxy")
+ nginxconf['KEEPPROXYSSLPORT'] = external_port_from_config("Keepproxy")
+ nginxconf['GITPORT'] = internal_port_from_config("GitHTTP")
+ nginxconf['GITSSLPORT'] = external_port_from_config("GitHTTP")
+ nginxconf['WSPORT'] = internal_port_from_config("Websocket")
+ nginxconf['WSSPORT'] = external_port_from_config("Websocket")
nginxconf['SSLCERT'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.pem')
nginxconf['SSLKEY'] = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'self-signed.key')
nginxconf['ACCESSLOG'] = _logfilename('nginx_access')
'-g', 'pid '+_pidfile('nginx')+';',
'-c', conffile],
env=env, stdin=open('/dev/null'), stdout=sys.stderr)
- _setport('controller-ssl', nginxconf['CONTROLLERSSLPORT'])
- _setport('keep-web-dl-ssl', nginxconf['KEEPWEBDLSSLPORT'])
- _setport('keep-web-ssl', nginxconf['KEEPWEBSSLPORT'])
- _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
- _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
+
+def setup_config():
+ rails_api_port = find_available_port()
+ controller_port = find_available_port()
+ controller_external_port = find_available_port()
+ websocket_port = find_available_port()
+ websocket_external_port = find_available_port()
+ git_httpd_port = find_available_port()
+ git_httpd_external_port = find_available_port()
+ keepproxy_port = find_available_port()
+ keepproxy_external_port = find_available_port()
+ keep_web_port = find_available_port()
+ keep_web_external_port = find_available_port()
+ keep_web_dl_port = find_available_port()
+ keep_web_dl_external_port = find_available_port()
+
+ dbconf = os.path.join(os.environ["CONFIGSRC"], "config.yml")
+
+ print("Getting config from %s" % dbconf, file=sys.stderr)
+
+ pgconnection = yaml.safe_load(open(dbconf))["Clusters"]["zzzzz"]["PostgreSQL"]["Connection"]
+
+ localhost = "127.0.0.1"
+ services = {
+ "RailsAPI": {
+ "InternalURLs": {
+ "https://%s:%s"%(localhost, rails_api_port): {}
+ }
+ },
+ "Controller": {
+ "ExternalURL": "https://%s:%s" % (localhost, controller_external_port),
+ "InternalURLs": {
+ "http://%s:%s"%(localhost, controller_port): {}
+ }
+ },
+ "Websocket": {
+ "ExternalURL": "wss://%s:%s/websocket" % (localhost, websocket_external_port),
+ "InternalURLs": {
+ "http://%s:%s"%(localhost, websocket_port): {}
+ }
+ },
+ "GitHTTP": {
+ "ExternalURL": "https://%s:%s" % (localhost, git_httpd_external_port),
+ "InternalURLs": {
+ "http://%s:%s"%(localhost, git_httpd_port): {}
+ }
+ },
+ "Keepproxy": {
+ "ExternalURL": "https://%s:%s" % (localhost, keepproxy_external_port),
+ "InternalURLs": {
+ "http://%s:%s"%(localhost, keepproxy_port): {}
+ }
+ },
+ "WebDAV": {
+ "ExternalURL": "https://%s:%s" % (localhost, keep_web_external_port),
+ "InternalURLs": {
+ "http://%s:%s"%(localhost, keep_web_port): {}
+ }
+ },
+ "WebDAVDownload": {
+ "ExternalURL": "https://%s:%s" % (localhost, keep_web_dl_external_port),
+ "InternalURLs": {
+ "http://%s:%s"%(localhost, keep_web_dl_port): {}
+ }
+ }
+ }
+
+ config = {
+ "Clusters": {
+ "zzzzz": {
+ "EnableBetaController14287": ('14287' in os.environ.get('ARVADOS_EXPERIMENTAL', '')),
+ "ManagementToken": "e687950a23c3a9bceec28c6223a06c79",
+ "API": {
+ "RequestTimeout": "30s"
+ },
+ "SystemLogs": {
+ "LogLevel": ('info' if os.environ.get('ARVADOS_DEBUG', '') in ['','0'] else 'debug')
+ },
+ "PostgreSQL": {
+ "Connection": pgconnection,
+ },
+ "TLS": {
+ "Insecure": True
+ },
+ "Services": services
+ }
+ }
+ }
+
+ conf = os.path.join(TEST_TMPDIR, 'arvados.yml')
+ with open(conf, 'w') as f:
+ yaml.safe_dump(config, f)
+
+ ex = "export ARVADOS_CONFIG="+conf
+ print(ex)
+
def stop_nginx():
if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
def _pidfile(program):
return os.path.join(TEST_TMPDIR, program + '.pid')
-def _portfile(program):
- return os.path.join(TEST_TMPDIR, program + '.port')
-
-def _setport(program, port):
- with open(_portfile(program), 'w') as f:
- f.write(str(port))
-
-# Returns 9 if program is not up.
-def _getport(program):
- try:
- return int(open(_portfile(program)).read())
- except IOError:
- return 9
-
-def _dbconfig(key):
- global _cached_db_config
- if not _cached_db_config:
- _cached_db_config = yaml.load(open(os.path.join(
- SERVICES_SRC_DIR, 'api', 'config', 'database.yml')))
- return _cached_db_config['test'][key]
-
-def _apiconfig(key):
- global _cached_config
- if _cached_config:
- return _cached_config[key]
- def _load(f, required=True):
- fullpath = os.path.join(SERVICES_SRC_DIR, 'api', 'config', f)
- if not required and not os.path.exists(fullpath):
- return {}
- return yaml.load(fullpath)
- cdefault = _load('application.default.yml')
- csite = _load('application.yml', required=False)
- _cached_config = {}
- for section in [cdefault.get('common',{}), cdefault.get('test',{}),
- csite.get('common',{}), csite.get('test',{})]:
- _cached_config.update(section)
- return _cached_config[key]
-
def fixture(fix):
'''load a fixture yaml file'''
with open(os.path.join(SERVICES_SRC_DIR, 'api', "test", "fixtures",
yaml_file = yaml_file[0:trim_index]
except ValueError:
pass
- return yaml.load(yaml_file)
+ return yaml.safe_load(yaml_file)
def auth_token(token_name):
return fixture("api_client_authorizations")[token_name]["api_token"]
'start_keep_proxy', 'stop_keep_proxy',
'start_keep-web', 'stop_keep-web',
'start_arv-git-httpd', 'stop_arv-git-httpd',
- 'start_nginx', 'stop_nginx',
+ 'start_nginx', 'stop_nginx', 'setup_config',
]
parser = argparse.ArgumentParser()
parser.add_argument('action', type=str, help="one of {}".format(actions))
stop_keep_web()
elif args.action == 'start_nginx':
run_nginx()
- print("export ARVADOS_API_HOST=0.0.0.0:{}".format(_getport('controller-ssl')))
+ print("export ARVADOS_API_HOST=0.0.0.0:{}".format(external_port_from_config('Controller')))
elif args.action == 'stop_nginx':
stop_nginx()
+ elif args.action == 'setup_config':
+ setup_config()
else:
raise Exception("action recognized but not implemented!?")