5416: Run arv-git-httpd and nginx ssl proxy in test suite.
authorTom Clegg <tom@curoverse.com>
Wed, 8 Apr 2015 14:22:05 +0000 (10:22 -0400)
committerTom Clegg <tom@curoverse.com>
Mon, 20 Apr 2015 20:58:51 +0000 (16:58 -0400)
apps/workbench/test/integration/jobs_test.rb
apps/workbench/test/integration/repositories_browse_test.rb
apps/workbench/test/test_helper.rb
sdk/python/tests/nginx.conf [new file with mode: 0644]
sdk/python/tests/run_test_server.py
services/api/test/helpers/git_test_helper.rb

index ce14ec6f761a57e33fcee05a597f52733ded4b43..2cae500027aeebd8f79270a4ba26f61e4496373f 100644 (file)
@@ -98,7 +98,7 @@ class JobsTest < ActionDispatch::IntegrationTest
       # that the error message says something appropriate for that
       # situation.
       if expect_options && use_latest
-        assert_text "Script version #{job['supplied_script_version']} does not resolve to a commit"
+        assert_text "077ba2ad3ea24a929091a9e6ce545c93199b8e57"
       else
         assert_text "Script version #{job['script_version']} does not resolve to a commit"
       end
index 147bf464be0ad754f31b317d2309c2b877bd255e..a6a85b5e4db04705604df37c0a1ffd7e24c28e85 100644 (file)
@@ -34,4 +34,20 @@ class RepositoriesTest < ActionDispatch::IntegrationTest
     click_on sha1
     assert_text fakecommit
   end
+
+  test "browse using arv-git-http" do
+    repo = api_fixture('repositories')['foo']
+    portfile =
+      File.expand_path('../../../../../tmp/arv-git-httpd-ssl.port', __FILE__)
+    gitsslport = File.read(portfile)
+    Repository.any_instance.
+      stubs(:http_fetch_url).
+      returns "https://localhost:#{gitsslport}/#{repo['name']}.git"
+    commit_sha1 = '1de84a854e2b440dc53bf42f8548afa4c17da332'
+    visit page_with_token('active', "/repositories/#{repo['uuid']}/commit/#{commit_sha1}")
+    assert_text "Date:   Tue Mar 18 15:55:28 2014 -0400"
+    visit page_with_token('active', "/repositories/#{repo['uuid']}/tree/#{commit_sha1}")
+    assert_selector "tbody td a", "foo"
+    assert_text "12 bytes"
+  end
 end
index 630a64f289a2515649c997c048dac6ff65091f8c..f335722c07673613cc15a192b8b9d191b3a605cc 100644 (file)
@@ -137,7 +137,7 @@ class ApiServerForTests
   @main_process_pid = $$
   @@server_is_running = false
 
-  def check_call *args
+  def check_output *args
     output = nil
     Bundler.with_clean_env do
       output = IO.popen *args do |io|
@@ -153,7 +153,12 @@ class ApiServerForTests
   def run_test_server
     env_script = nil
     Dir.chdir PYTHON_TESTS_DIR do
-      env_script = check_call %w(python ./run_test_server.py start --auth admin)
+      # These are no-ops if we're running within run-tests.sh (except
+      # that we do get a useful env_script back from "start", even
+      # though it doesn't need to start up a new server).
+      env_script = check_output %w(python ./run_test_server.py start --auth admin)
+      check_output %w(python ./run_test_server.py start_arv-git-httpd)
+      check_output %w(python ./run_test_server.py start_nginx)
     end
     test_env = {}
     env_script.each_line do |line|
@@ -169,8 +174,10 @@ class ApiServerForTests
 
   def stop_test_server
     Dir.chdir PYTHON_TESTS_DIR do
-      # This is a no-op if we're running within run-tests.sh
-      check_call %w(python ./run_test_server.py stop)
+      # These are no-ops if we're running within run-tests.sh
+      check_output %w(python ./run_test_server.py stop_nginx)
+      check_output %w(python ./run_test_server.py stop_arv-git-httpd)
+      check_output %w(python ./run_test_server.py stop)
     end
     @@server_is_running = false
   end
@@ -196,7 +203,7 @@ class ApiServerForTests
 
   def run_rake_task task_name, arg_string
     Dir.chdir ARV_API_SERVER_DIR do
-      check_call ['bundle', 'exec', 'rake', "#{task_name}[#{arg_string}]"]
+      check_output ['bundle', 'exec', 'rake', "#{task_name}[#{arg_string}]"]
     end
   end
 end
diff --git a/sdk/python/tests/nginx.conf b/sdk/python/tests/nginx.conf
new file mode 100644 (file)
index 0000000..6196605
--- /dev/null
@@ -0,0 +1,31 @@
+daemon off;
+error_log stderr info;          # Yes, must be specified here _and_ cmdline
+events {
+}
+http {
+  access_log /dev/stderr combined;
+  upstream arv-git-http {
+    server localhost:{{GITPORT}};
+  }
+  server {
+    listen *:{{GITSSLPORT}} ssl default_server;
+    server_name _;
+    ssl_certificate {{SSLCERT}};
+    ssl_certificate_key {{SSLKEY}};
+    location  / {
+      proxy_pass http://arv-git-http;
+    }
+  }
+  upstream keepproxy {
+    server localhost:{{KEEPPROXYPORT}};
+  }
+  server {
+    listen *:{{KEEPPROXYSSLPORT}} ssl default_server;
+    server_name _;
+    ssl_certificate {{SSLCERT}};
+    ssl_certificate_key {{SSLKEY}};
+    location  / {
+      proxy_pass http://keepproxy;
+    }
+  }
+}
index 51fe43f9e5deab9c1323ef4003f0f15aba1d1626..c54dad0c5f17bc654dc1e45743e244773a821f95 100644 (file)
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 
+from __future__ import print_function
 import argparse
 import atexit
 import httplib2
@@ -41,6 +42,7 @@ if not os.path.exists(TEST_TMPDIR):
     os.mkdir(TEST_TMPDIR)
 
 my_api_host = None
+_cached_config = {}
 
 def find_server_pid(PID_PATH, wait=10):
     now = time.time()
@@ -178,6 +180,13 @@ def run(leave_running_atexit=False):
             '-subj', '/CN=0.0.0.0'],
         stdout=sys.stderr)
 
+    # Install the git repository fixtures.
+    gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
+    gittarball = os.path.join(SERVICES_SRC_DIR, 'api', 'test', 'test.git.tar')
+    if not os.path.isdir(gitdir):
+        os.makedirs(gitdir)
+    subprocess.check_output(['tar', '-xC', gitdir, '-f', gittarball])
+
     port = find_available_port()
     env = os.environ.copy()
     env['RAILS_ENV'] = 'test'
@@ -258,13 +267,14 @@ def _start_keep(n, keep_args):
     keep_cmd = ["keepstore",
                 "-volume={}".format(keep0),
                 "-listen=:{}".format(port),
-                "-pid={}".format("{}/keep{}.pid".format(TEST_TMPDIR, n))]
+                "-pid="+_pidfile('keep{}'.format(n))]
 
     for arg, val in keep_args.iteritems():
         keep_cmd.append("{}={}".format(arg, val))
 
-    kp0 = subprocess.Popen(keep_cmd)
-    with open("{}/keep{}.pid".format(TEST_TMPDIR, n), 'w') as f:
+    kp0 = subprocess.Popen(
+        keep_cmd, stdin=open('/dev/null'), stdout=sys.stderr)
+    with open(_pidfile('keep{}'.format(n)), 'w') as f:
         f.write(str(kp0.pid))
 
     with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'w') as f:
@@ -307,7 +317,7 @@ def run_keep(blob_signing_key=None, enforce_permissions=False):
         }).execute()
 
 def _stop_keep(n):
-    kill_server_pid("{}/keep{}.pid".format(TEST_TMPDIR, n), 0)
+    kill_server_pid(_pidfile('keep{}'.format(n)), 0)
     if os.path.exists("{}/keep{}.volume".format(TEST_TMPDIR, n)):
         with open("{}/keep{}.volume".format(TEST_TMPDIR, n), 'r') as r:
             shutil.rmtree(r.read(), True)
@@ -320,6 +330,8 @@ def stop_keep():
     _stop_keep(1)
 
 def run_keep_proxy():
+    if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
+        return
     stop_keep_proxy()
 
     admin_token = auth_token('admin')
@@ -328,9 +340,9 @@ def run_keep_proxy():
     env['ARVADOS_API_TOKEN'] = admin_token
     kp = subprocess.Popen(
         ['keepproxy',
-         '-pid={}/keepproxy.pid'.format(TEST_TMPDIR),
+         '-pid='+_pidfile('keepproxy'),
          '-listen=:{}'.format(port)],
-        env=env)
+        env=env, stdin=open('/dev/null'), stdout=sys.stderr)
 
     api = arvados.api(
         version='v1',
@@ -347,9 +359,100 @@ def run_keep_proxy():
         'service_ssl_flag': False,
     }}).execute()
     os.environ["ARVADOS_KEEP_PROXY"] = "http://localhost:{}".format(port)
+    _setport('keepproxy', port)
 
 def stop_keep_proxy():
-    kill_server_pid(os.path.join(TEST_TMPDIR, "keepproxy.pid"), 0)
+    if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
+        return
+    kill_server_pid(_pidfile('keepproxy'), wait=0)
+
+def run_arv_git_httpd():
+    if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
+        return
+    stop_arv_git_httpd()
+
+    gitdir = os.path.join(SERVICES_SRC_DIR, 'api', 'tmp', 'git')
+    gitport = find_available_port()
+    env = os.environ.copy()
+    del env['ARVADOS_API_TOKEN']
+    agh = subprocess.Popen(
+        ['arv-git-httpd',
+         '-repo-root='+gitdir+'/test',
+         '-address=:'+str(gitport)],
+        env=env, stdin=open('/dev/null'), stdout=sys.stderr)
+    with open(_pidfile('arv-git-httpd'), 'w') as f:
+        f.write(str(agh.pid))
+    _setport('arv-git-httpd', gitport)
+
+def stop_arv_git_httpd():
+    if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
+        return
+    kill_server_pid(_pidfile('arv-git-httpd'), wait=0)
+
+def run_nginx():
+    if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
+        return
+    nginxconf = {}
+    nginxconf['KEEPPROXYPORT'] = _getport('keepproxy')
+    nginxconf['KEEPPROXYSSLPORT'] = find_available_port()
+    nginxconf['GITPORT'] = _getport('arv-git-httpd')
+    nginxconf['GITSSLPORT'] = find_available_port()
+    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')
+
+    conftemplatefile = os.path.join(MY_DIRNAME, 'nginx.conf')
+    conffile = os.path.join(TEST_TMPDIR, 'nginx.conf')
+    with open(conffile, 'w') as f:
+        f.write(re.sub(
+            r'{{([A-Z]+)}}',
+            lambda match: str(nginxconf.get(match.group(1))),
+            open(conftemplatefile).read()))
+
+    env = os.environ.copy()
+    env['PATH'] = env['PATH']+':/sbin:/usr/sbin:/usr/local/sbin'
+    nginx = subprocess.Popen(
+        ['nginx',
+         '-g', 'error_log stderr info;',
+         '-g', 'pid '+_pidfile('nginx')+';',
+         '-c', conffile],
+        env=env, stdin=open('/dev/null'), stdout=sys.stderr)
+    _setport('keepproxy-ssl', nginxconf['KEEPPROXYSSLPORT'])
+    _setport('arv-git-httpd-ssl', nginxconf['GITSSLPORT'])
+
+def stop_nginx():
+    if 'ARVADOS_TEST_PROXY_SERVICES' in os.environ:
+        return
+    kill_server_pid(_pidfile('nginx'), wait=0)
+
+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 _apiconfig(key):
+    if _cached_config:
+        return _cached_config[key]
+    def _load(f):
+        return yaml.load(os.path.join(SERVICES_SRC_DIR, 'api', 'config', f))
+    cdefault = _load('application.default.yml')
+    csite = _load('application.yml')
+    _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'''
@@ -431,14 +534,21 @@ class TestCaseWithServers(unittest.TestCase):
 
 
 if __name__ == "__main__":
-    actions = ['start', 'stop',
-               'start_keep', 'stop_keep',
-               'start_keep_proxy', 'stop_keep_proxy']
+    actions = [
+        'start', 'stop',
+        'start_keep', 'stop_keep',
+        'start_keep_proxy', 'stop_keep_proxy',
+        'start_arv-git-httpd', 'stop_arv-git-httpd',
+        'start_nginx', 'stop_nginx',
+    ]
     parser = argparse.ArgumentParser()
     parser.add_argument('action', type=str, help="one of {}".format(actions))
     parser.add_argument('--auth', type=str, metavar='FIXTURE_NAME', help='Print authorization info for given api_client_authorizations fixture')
     args = parser.parse_args()
 
+    if args.action not in actions:
+        print("Unrecognized action '{}'. Actions are: {}.".format(args.action, actions), file=sys.stderr)
+        sys.exit(1)
     if args.action == 'start':
         stop(force=('ARVADOS_TEST_API_HOST' not in os.environ))
         run(leave_running_atexit=True)
@@ -460,5 +570,13 @@ if __name__ == "__main__":
         run_keep_proxy()
     elif args.action == 'stop_keep_proxy':
         stop_keep_proxy()
+    elif args.action == 'start_arv-git-httpd':
+        run_arv_git_httpd()
+    elif args.action == 'stop_arv-git-httpd':
+        stop_arv_git_httpd()
+    elif args.action == 'start_nginx':
+        run_nginx()
+    elif args.action == 'stop_nginx':
+        stop_nginx()
     else:
-        print("Unrecognized action '{}'. Actions are: {}.".format(args.action, actions))
+        raise Exception("action recognized but not implemented!?")
index 9abdc4f0d926a0481c647ca3fede3491bd65ff46..6fce321953d3add8138056306629500927771f65 100644 (file)
@@ -14,9 +14,15 @@ require 'tmpdir'
 module GitTestHelper
   def self.included base
     base.setup do
-      @tmpdir = Dir.mktmpdir()
-      system("tar", "-xC", @tmpdir, "-f", "test/test.git.tar")
+      # Extract the test repository data into the default test
+      # environment's Rails.configuration.git_repositories_dir. (We
+      # don't use that config setting here, though: it doesn't seem
+      # worth the risk of stepping on a real git repo root.)
+      @tmpdir = Rails.root.join 'tmp', 'git'
+      FileUtils.mkdir_p @tmpdir
+      system("tar", "-xC", @tmpdir.to_s, "-f", "test/test.git.tar")
       Rails.configuration.git_repositories_dir = "#{@tmpdir}/test"
+
       intdir = Rails.configuration.git_internal_dir
       if not File.exist? intdir
         FileUtils.mkdir_p intdir