Blame tests/test_pagure_repospanner.py

Patrick Uiterwijk 3f97f6
# -*- coding: utf-8 -*-
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
"""
Patrick Uiterwijk 3f97f6
 (c) 2015-2018 - Copyright Red Hat Inc
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
 Authors:
Patrick Uiterwijk 3f97f6
   Patrick Uiterwijk <puiterwijk@redhat.com></puiterwijk@redhat.com>
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
"""
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 67d1cc
from __future__ import unicode_literals, absolute_import
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
import datetime
Patrick Uiterwijk 69ea3d
import functools
Patrick Uiterwijk d29158
import munch
Patrick Uiterwijk 3f97f6
import unittest
Patrick Uiterwijk 3f97f6
import shutil
Patrick Uiterwijk 3f97f6
import subprocess
Patrick Uiterwijk 3f97f6
import sys
Patrick Uiterwijk 3f97f6
import tempfile
Patrick Uiterwijk 3f97f6
import time
Patrick Uiterwijk 3f97f6
import os
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
import six
Patrick Uiterwijk 3f97f6
import json
Patrick Uiterwijk 3f97f6
import pygit2
Patrick Uiterwijk 3f97f6
import requests
Patrick Uiterwijk 3f97f6
from requests.adapters import HTTPAdapter
Patrick Uiterwijk 3f97f6
from requests.packages.urllib3.util.retry import Retry
Patrick Uiterwijk 3f97f6
from mock import patch, MagicMock
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
sys.path.insert(
Pierre-Yves Chibon 73d120
    0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
Pierre-Yves Chibon 73d120
)
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 930073
import pagure.lib.query
Patrick Uiterwijk d29158
import pagure.cli.admin
Patrick Uiterwijk 3f97f6
import tests
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
REPOSPANNER_CONFIG_TEMPLATE = """
Patrick Uiterwijk 3f97f6
---
Patrick Uiterwijk 3f97f6
ca:
Patrick Uiterwijk 3f97f6
  path: %(path)s/repospanner/pki
Patrick Uiterwijk 3f97f6
admin:
Patrick Uiterwijk 9b2de7
  url:  https://localhost.localdomain:%(gitport)s/
Patrick Uiterwijk 3f97f6
  ca:   %(path)s/repospanner/pki/ca.crt
Patrick Uiterwijk 3f97f6
  cert: %(path)s/repospanner/pki/admin.crt
Patrick Uiterwijk 3f97f6
  key:  %(path)s/repospanner/pki/admin.key
Patrick Uiterwijk 3f97f6
storage:
Patrick Uiterwijk 3f97f6
  state: %(path)s/repospanner/state
Patrick Uiterwijk 3f97f6
  git:
Patrick Uiterwijk 3f97f6
    type: tree
Patrick Uiterwijk 3f97f6
    clustered: true
Patrick Uiterwijk 3f97f6
    directory: %(path)s/repospanner/git
Patrick Uiterwijk 3f97f6
listen:
Patrick Uiterwijk 3f97f6
  rpc:  127.0.0.1:%(rpcport)s
Patrick Uiterwijk 3f97f6
  http: 127.0.0.1:%(gitport)s
Patrick Uiterwijk 3f97f6
certificates:
Patrick Uiterwijk 3f97f6
  ca: %(path)s/repospanner/pki/ca.crt
Patrick Uiterwijk 3f97f6
  client:
Patrick Uiterwijk 9b2de7
    cert: %(path)s/repospanner/pki/repospanner.localhost.crt
Patrick Uiterwijk 9b2de7
    key:  %(path)s/repospanner/pki/repospanner.localhost.key
Patrick Uiterwijk 3f97f6
  server:
Patrick Uiterwijk 3f97f6
    default:
Patrick Uiterwijk 9b2de7
      cert: %(path)s/repospanner/pki/repospanner.localhost.crt
Patrick Uiterwijk 9b2de7
      key:  %(path)s/repospanner/pki/repospanner.localhost.key
Patrick Uiterwijk 3f97f6
hooks:
Patrick Uiterwijk 21f935
  debug: true
Patrick Uiterwijk 3f97f6
  bubblewrap:
Patrick Uiterwijk cf1396
    enabled: false
Patrick Uiterwijk 3f97f6
    unshare:
Patrick Uiterwijk 3f97f6
    - net
Patrick Uiterwijk 3f97f6
    - ipc
Patrick Uiterwijk 3f97f6
    - pid
Patrick Uiterwijk 3f97f6
    - uts
Patrick Uiterwijk 3f97f6
    share_net: false
Patrick Uiterwijk 3f97f6
    mount_proc: true
Patrick Uiterwijk 3f97f6
    mount_dev: true
Patrick Uiterwijk 3f97f6
    uid:
Patrick Uiterwijk 3f97f6
    gid:
Patrick Uiterwijk 3f97f6
    hostname: myhostname
Patrick Uiterwijk 3f97f6
    bind:
Patrick Uiterwijk 3f97f6
    ro_bind:
Patrick Uiterwijk d29158
    - - /usr
Patrick Uiterwijk d29158
      - /usr
Patrick Uiterwijk d29158
    - - %(codepath)s
Patrick Uiterwijk d29158
      - %(codepath)s
Patrick Uiterwijk d29158
    - - %(path)s
Patrick Uiterwijk d29158
      - %(path)s
Patrick Uiterwijk d29158
    - - %(crosspath)s
Patrick Uiterwijk d29158
      - %(crosspath)s
Patrick Uiterwijk 3f97f6
    symlink:
Patrick Uiterwijk d29158
    - - usr/lib64
Patrick Uiterwijk d29158
      - /lib64
Patrick Uiterwijk d29158
    - - usr/bin
Patrick Uiterwijk d29158
      - /bin
Patrick Uiterwijk d29158
  runner: %(hookrunner_bin)s
Patrick Uiterwijk 3f97f6
  user: 0
Patrick Uiterwijk 3f97f6
"""
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
class PagureRepoSpannerTests(tests.Modeltests):
Patrick Uiterwijk 3f97f6
    """ Tests for repoSpanner integration of pagure """
Pierre-Yves Chibon 73d120
Patrick Uiterwijk 3f97f6
    repospanner_binary = None
Patrick Uiterwijk 3f97f6
    repospanner_runlog = None
Patrick Uiterwijk 3f97f6
    repospanner_proc = None
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
    def run_cacmd(self, logfile, *args):
Patrick Uiterwijk 3f97f6
        """ Run a repoSpanner CA command. """
Patrick Uiterwijk 3f97f6
        subprocess.check_call(
Pierre-Yves Chibon 73d120
            [
Pierre-Yves Chibon 73d120
                self.repospanner_binary,
Pierre-Yves Chibon 73d120
                "--config",
Pierre-Yves Chibon 73d120
                os.path.join(self.path, "repospanner", "config.yml"),
Pierre-Yves Chibon 73d120
                # NEVER use this in a production system! It makes repeatable keys
Pierre-Yves Chibon 73d120
                "ca",
Pierre-Yves Chibon 73d120
            ]
Pierre-Yves Chibon 73d120
            + list(args)
Pierre-Yves Chibon 73d120
            + ["--very-insecure-weak-keys"],
Patrick Uiterwijk 3f97f6
            stdout=logfile,
Patrick Uiterwijk 3f97f6
            stderr=subprocess.STDOUT,
Patrick Uiterwijk 3f97f6
        )
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
    def setUp(self):
Patrick Uiterwijk 3f97f6
        """ set up the environment. """
Pierre-Yves Chibon 73d120
        possible_paths = ["./repospanner", "/usr/bin/repospanner"]
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        for option in possible_paths:
Patrick Uiterwijk 3f97f6
            option = os.path.abspath(option)
Patrick Uiterwijk 3f97f6
            if os.path.exists(option):
Patrick Uiterwijk 3f97f6
                self.repospanner_binary = option
Patrick Uiterwijk 3f97f6
                break
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        if not self.repospanner_binary:
Pierre-Yves Chibon 73d120
            raise unittest.SkipTest("repoSpanner not found")
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 37fdbb
        hookrunbins = [
Pierre-Yves Chibon 37fdbb
            os.path.join(
Pierre-Yves Chibon 73d120
                os.path.dirname(self.repospanner_binary), "repohookrunner"
Pierre-Yves Chibon 73d120
            ),
Pierre-Yves Chibon 73d120
            os.path.join("/usr", "libexec", "repohookrunner"),
Pierre-Yves Chibon 37fdbb
        ]
Pierre-Yves Chibon 37fdbb
        found = False
Pierre-Yves Chibon 37fdbb
        for hookrunbin in hookrunbins:
Pierre-Yves Chibon 37fdbb
            if os.path.exists(hookrunbin):
Pierre-Yves Chibon 37fdbb
                found = True
Pierre-Yves Chibon 37fdbb
                break
Pierre-Yves Chibon 37fdbb
        if not found:
Pierre-Yves Chibon 73d120
            raise Exception("repoSpanner found, but repohookrunner not")
Pierre-Yves Chibon 37fdbb
Pierre-Yves Chibon 37fdbb
        repobridgebins = [
Pierre-Yves Chibon 37fdbb
            os.path.join(
Pierre-Yves Chibon 73d120
                os.path.dirname(self.repospanner_binary), "repobridge"
Pierre-Yves Chibon 73d120
            ),
Pierre-Yves Chibon 73d120
            os.path.join("/usr", "libexec", "repobridge"),
Pierre-Yves Chibon 37fdbb
        ]
Pierre-Yves Chibon 37fdbb
        found = False
Pierre-Yves Chibon 37fdbb
        for repobridgebin in repobridgebins:
Pierre-Yves Chibon 37fdbb
            if os.path.exists(repobridgebin):
Pierre-Yves Chibon 37fdbb
                found = True
Pierre-Yves Chibon 37fdbb
                break
Pierre-Yves Chibon 37fdbb
        if not found:
Pierre-Yves Chibon 73d120
            raise Exception("repoSpanner found, but repobridge not")
Patrick Uiterwijk 8174a4
Pierre-Yves Chibon 73d120
        self.config_values["repobridge_binary"] = repobridgebin
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
        codepath = os.path.normpath(
Pierre-Yves Chibon 73d120
            os.path.join(os.path.dirname(os.path.abspath(__file__)), "../")
Pierre-Yves Chibon 73d120
        )
Patrick Uiterwijk d29158
Patrick Uiterwijk 3f97f6
        # Only run the setUp() function if we are actually going ahead and run
Patrick Uiterwijk 3f97f6
        # this test. The reason being that otherwise, setUp will set up a
Patrick Uiterwijk 3f97f6
        # database, but because we "error out" from setUp, the tearDown()
Patrick Uiterwijk 3f97f6
        # function never gets called, leaving it behind.
Patrick Uiterwijk 3f97f6
        super(PagureRepoSpannerTests, self).setUp()
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        # TODO: Find free ports
Patrick Uiterwijk 3f97f6
        configvals = {
Pierre-Yves Chibon 73d120
            "path": self.path,
Pierre-Yves Chibon 73d120
            "crosspath": tests.tests_state["path"],
Pierre-Yves Chibon 73d120
            "gitport": 8443 + sys.version_info.major,
Pierre-Yves Chibon 73d120
            "rpcport": 8445 + sys.version_info.major,
Pierre-Yves Chibon 73d120
            "codepath": codepath,
Pierre-Yves Chibon 73d120
            "hookrunner_bin": hookrunbin,
Patrick Uiterwijk 3f97f6
        }
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
        os.mkdir(os.path.join(self.path, "repospanner"))
Pierre-Yves Chibon 73d120
        cfgpath = os.path.join(self.path, "repospanner", "config.yml")
Pierre-Yves Chibon 73d120
        with open(cfgpath, "w") as cfg:
Patrick Uiterwijk 3f97f6
            cfg.write(REPOSPANNER_CONFIG_TEMPLATE % configvals)
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
        with open(
Pierre-Yves Chibon 73d120
            os.path.join(self.path, "repospanner", "keylog"), "w"
Pierre-Yves Chibon 73d120
        ) as keylog:
Patrick Uiterwijk 3f97f6
            # Create the CA
Pierre-Yves Chibon 73d120
            self.run_cacmd(
Pierre-Yves Chibon 73d120
                keylog,
Pierre-Yves Chibon 73d120
                "init",
Pierre-Yves Chibon 73d120
                "localdomain",
Pierre-Yves Chibon 73d120
                "--no-name-constraint",
Pierre-Yves Chibon 73d120
                "--random-cn",
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 3f97f6
            # Create the node cert
Pierre-Yves Chibon 73d120
            self.run_cacmd(keylog, "node", "localhost", "repospanner")
Patrick Uiterwijk 3f97f6
            # Create the admin cert
Pierre-Yves Chibon 73d120
            self.run_cacmd(
Pierre-Yves Chibon 73d120
                keylog,
Pierre-Yves Chibon 73d120
                "leaf",
Pierre-Yves Chibon 73d120
                "admin",
Pierre-Yves Chibon 73d120
                "--admin",
Pierre-Yves Chibon 73d120
                "--region",
Pierre-Yves Chibon 73d120
                "*",
Pierre-Yves Chibon 73d120
                "--repo",
Pierre-Yves Chibon 73d120
                "*",
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 3f97f6
            # Create the Pagure cert
Pierre-Yves Chibon 73d120
            self.run_cacmd(
Pierre-Yves Chibon 73d120
                keylog,
Pierre-Yves Chibon 73d120
                "leaf",
Pierre-Yves Chibon 73d120
                "pagure",
Pierre-Yves Chibon 73d120
                "--read",
Pierre-Yves Chibon 73d120
                "--write",
Pierre-Yves Chibon 73d120
                "--region",
Pierre-Yves Chibon 73d120
                "*",
Pierre-Yves Chibon 73d120
                "--repo",
Pierre-Yves Chibon 73d120
                "*",
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
        with open(
Pierre-Yves Chibon 73d120
            os.path.join(self.path, "repospanner", "spawnlog"), "w"
Pierre-Yves Chibon 73d120
        ) as spawnlog:
Patrick Uiterwijk 3f97f6
            # Initialize state
Patrick Uiterwijk 3f97f6
            subprocess.check_call(
Pierre-Yves Chibon 73d120
                [
Pierre-Yves Chibon 73d120
                    self.repospanner_binary,
Pierre-Yves Chibon 73d120
                    "--config",
Pierre-Yves Chibon 73d120
                    cfgpath,
Pierre-Yves Chibon 73d120
                    "serve",
Pierre-Yves Chibon 73d120
                    "--spawn",
Pierre-Yves Chibon 73d120
                ],
Patrick Uiterwijk 3f97f6
                stdout=spawnlog,
Patrick Uiterwijk 3f97f6
                stderr=subprocess.STDOUT,
Patrick Uiterwijk 3f97f6
            )
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        self.repospanner_runlog = open(
Pierre-Yves Chibon 73d120
            os.path.join(self.path, "repospanner", "runlog"), "w+"
Pierre-Yves Chibon 73d120
        )
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        try:
Patrick Uiterwijk 3f97f6
            self.repospanner_proc = subprocess.Popen(
Pierre-Yves Chibon 73d120
                [
Pierre-Yves Chibon 73d120
                    self.repospanner_binary,
Pierre-Yves Chibon 73d120
                    "--config",
Pierre-Yves Chibon 73d120
                    cfgpath,
Pierre-Yves Chibon 73d120
                    "serve",
Pierre-Yves Chibon 73d120
                    "--debug",
Pierre-Yves Chibon 73d120
                ],
Patrick Uiterwijk 3f97f6
                stdout=self.repospanner_runlog,
Patrick Uiterwijk 3f97f6
                stderr=subprocess.STDOUT,
Patrick Uiterwijk 3f97f6
            )
Patrick Uiterwijk 3f97f6
        except:
Patrick Uiterwijk 3f97f6
            # Make sure to clean up repoSpanner, since we did start it
Patrick Uiterwijk 3f97f6
            self.tearDown()
Patrick Uiterwijk 3f97f6
            raise
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3bda5f
        attempts = 0
Patrick Uiterwijk 3bda5f
        while True:
Patrick Uiterwijk 3bda5f
            try:
Patrick Uiterwijk 3bda5f
                # Wait for the instance to become available
Patrick Uiterwijk 3bda5f
                resp = requests.get(
Pierre-Yves Chibon 73d120
                    "https://repospanner.localhost.localdomain:%d/"
Pierre-Yves Chibon 73d120
                    % configvals["gitport"],
Pierre-Yves Chibon 73d120
                    verify=os.path.join(
Pierre-Yves Chibon 73d120
                        self.path, "repospanner", "pki", "ca.crt"
Pierre-Yves Chibon 73d120
                    ),
Patrick Uiterwijk 3bda5f
                    cert=(
Pierre-Yves Chibon 73d120
                        os.path.join(
Pierre-Yves Chibon 73d120
                            self.path, "repospanner", "pki", "pagure.crt"
Pierre-Yves Chibon 73d120
                        ),
Pierre-Yves Chibon 73d120
                        os.path.join(
Pierre-Yves Chibon 73d120
                            self.path, "repospanner", "pki", "pagure.key"
Pierre-Yves Chibon 73d120
                        ),
Pierre-Yves Chibon 73d120
                    ),
Patrick Uiterwijk 3bda5f
                )
Patrick Uiterwijk 3bda5f
                resp.raise_for_status()
Patrick Uiterwijk 3bda5f
Pierre-Yves Chibon 73d120
                print("repoSpanner identification: %s" % resp.text)
Patrick Uiterwijk 3bda5f
                break
Patrick Uiterwijk 3bda5f
            except:
Patrick Uiterwijk 3bda5f
                if attempts < 5:
Patrick Uiterwijk 3bda5f
                    attempts += 1
Patrick Uiterwijk 3bda5f
                    time.sleep(1)
Patrick Uiterwijk 3bda5f
                    continue
Patrick Uiterwijk 3bda5f
                # Make sure to clean up repoSpanner, since we did start it
Patrick Uiterwijk 3bda5f
                self.tearDown()
Patrick Uiterwijk 3bda5f
                raise
Patrick Uiterwijk 3bda5f
Patrick Uiterwijk 880f5e
        # Upload the hook script to repoSpanner
Pierre-Yves Chibon 73d120
        args = munch.Munch({"region": "default"})
Patrick Uiterwijk 880f5e
        hookid = pagure.cli.admin.do_upload_repospanner_hooks(args)
Pierre-Yves Chibon 73d120
        pagure.config.config["REPOSPANNER_REGIONS"]["default"]["hook"] = hookid
Patrick Uiterwijk 880f5e
Patrick Uiterwijk 3f97f6
    def tearDown(self):
Patrick Uiterwijk 3f97f6
        """ Tear down the repoSpanner instance. """
Patrick Uiterwijk 3f97f6
        if self.repospanner_proc:
Patrick Uiterwijk 3f97f6
            # Tear down
Patrick Uiterwijk 3f97f6
            self.repospanner_proc.terminate()
Patrick Uiterwijk 3f97f6
            exitcode = self.repospanner_proc.wait()
Patrick Uiterwijk 3f97f6
            if exitcode != 0:
Pierre-Yves Chibon 73d120
                print("repoSpanner exit code: %d" % exitcode)
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        if self.repospanner_runlog:
Patrick Uiterwijk 3f97f6
            self.repospanner_runlog.close()
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        super(PagureRepoSpannerTests, self).tearDown()
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 69ea3d
def print_repospanner_log(fn):
Patrick Uiterwijk 69ea3d
    @functools.wraps(fn)
Patrick Uiterwijk 69ea3d
    def wrapper(self, *args, **kwargs):
Patrick Uiterwijk 69ea3d
        try:
Patrick Uiterwijk 69ea3d
            return fn(self, *args, **kwargs)
Patrick Uiterwijk 69ea3d
        finally:
Patrick Uiterwijk 69ea3d
            if self.repospanner_runlog:
Pierre-Yves Chibon 73d120
                self.repospanner_runlog.seek(0, 0)
Patrick Uiterwijk 69ea3d
                print("repoSpanner log follows:")
Patrick Uiterwijk 69ea3d
                print(self.repospanner_runlog.read())
Patrick Uiterwijk 69ea3d
Patrick Uiterwijk 69ea3d
    return wrapper
Patrick Uiterwijk 69ea3d
Patrick Uiterwijk 69ea3d
Patrick Uiterwijk 3f97f6
class PagureRepoSpannerTestsNewRepoDefault(PagureRepoSpannerTests):
Patrick Uiterwijk 3f97f6
    config_values = {
Pierre-Yves Chibon 73d120
        "repospanner_new_repo": "'default'",
Pierre-Yves Chibon 73d120
        "authbackend": "test_auth",
Patrick Uiterwijk 3f97f6
    }
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 69ea3d
    @print_repospanner_log
Pierre-Yves Chibon 73d120
    @patch("pagure.ui.app.admin_session_timedout")
Patrick Uiterwijk 3f97f6
    def test_new_project(self, ast):
Patrick Uiterwijk 3f97f6
        """ Test creating a new repo by default on repoSpanner works. """
Patrick Uiterwijk 3f97f6
        ast.return_value = False
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
        user = tests.FakeUser(username="foo")
Patrick Uiterwijk 3f97f6
        with tests.user_set(self.app.application, user):
Pierre-Yves Chibon 73d120
            output = self.app.get("/new/")
Patrick Uiterwijk 3f97f6
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk 3f97f6
            output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 73d120
            self.assertIn("Create new Project", output_text)
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
            data = {
Pierre-Yves Chibon 73d120
                "name": "project-1",
Pierre-Yves Chibon 73d120
                "description": "Project #1",
Pierre-Yves Chibon 73d120
                "create_readme": "y",
Pierre-Yves Chibon 73d120
                "csrf_token": self.get_csrf(),
Patrick Uiterwijk 3f97f6
            }
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
            output = self.app.post("/new/", data=data, follow_redirects=True)
Patrick Uiterwijk 3f97f6
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk 3f97f6
            output_text = output.get_data(as_text=True)
Patrick Uiterwijk 3f97f6
            self.assertIn(
Pierre-Yves Chibon 73d120
                '
\nProject #1', output_text
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 3f97f6
            self.assertIn(
Pierre-Yves Chibon 73d120
                "<title>Overview - project-1 - Pagure</title>", output_text
Pierre-Yves Chibon 73d120
            )
Pierre-Yves Chibon 73d120
            self.assertIn("Added the README", output_text)
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
            output = self.app.get("/project-1/settings")
Patrick Uiterwijk 3f97f6
            self.assertIn(
Pierre-Yves Chibon 73d120
                "This repository is on repoSpanner region default",
Pierre-Yves Chibon 73d120
                output.get_data(as_text=True),
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
        with tests.user_set(
Pierre-Yves Chibon 73d120
            self.app.application, tests.FakeUser(username="pingou")
Pierre-Yves Chibon 73d120
        ):
Patrick Uiterwijk 3c1099
            # Verify that for forking, Git auth status is ignored (hooks should not be run)
Patrick Uiterwijk 3c1099
            self.set_auth_status(False)
Patrick Uiterwijk 3c1099
Pierre-Yves Chibon 73d120
            data = {"csrf_token": self.get_csrf()}
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
            output = self.app.post(
Pierre-Yves Chibon 73d120
                "/do_fork/project-1", data=data, follow_redirects=True
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 3f97f6
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk 3f97f6
            output_text = output.get_data(as_text=True)
Patrick Uiterwijk 3f97f6
            self.assertIn(
Pierre-Yves Chibon 73d120
                '
\nProject #1', output_text
Pierre-Yves Chibon 73d120
            )
Pierre-Yves Chibon 73d120
            self.assertIn(
Pierre-Yves Chibon 73d120
                "<title>Overview - project-1 - Pagure</title>", output_text
Pierre-Yves Chibon 73d120
            )
Pierre-Yves Chibon 73d120
            self.assertIn("Added the README", output_text)
Patrick Uiterwijk 3f97f6
            self.assertIn(
Pierre-Yves Chibon 73d120
                "/?next=http://localhost/fork/pingou/project-1", output_text
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
            output = self.app.get("/fork/pingou/project-1/settings")
Patrick Uiterwijk 3f97f6
            self.assertIn(
Pierre-Yves Chibon 73d120
                "This repository is on repoSpanner region default",
Pierre-Yves Chibon 73d120
                output.get_data(as_text=True),
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 3f97f6
        # Verify that only pseudo repos exist, and no on-disk repos got created
Pierre-Yves Chibon 73d120
        repodirlist = os.listdir(os.path.join(self.path, "repos"))
Pierre-Yves Chibon 73d120
        self.assertEqual(repodirlist, ["pseudo"])
Patrick Uiterwijk 3f97f6
Patrick Uiterwijk 69ea3d
    @print_repospanner_log
Pierre-Yves Chibon 73d120
    @patch.dict(
Pierre-Yves Chibon 73d120
        "pagure.config.config",
Pierre-Yves Chibon 73d120
        {
Pierre-Yves Chibon 73d120
            "ALLOW_HTTP_PULL_PUSH": True,
Pierre-Yves Chibon 73d120
            "ALLOW_HTTP_PUSH": True,
Pierre-Yves Chibon 73d120
            "HTTP_REPO_ACCESS_GITOLITE": False,
Pierre-Yves Chibon 73d120
        },
Pierre-Yves Chibon 73d120
    )
Patrick Uiterwijk a50651
    def test_http_pull(self):
Patrick Uiterwijk a50651
        """ Test that the HTTP pull endpoint works for repoSpanner. """
Patrick Uiterwijk a50651
        tests.create_projects(self.session)
Patrick Uiterwijk a50651
        tests.create_tokens(self.session)
Patrick Uiterwijk a50651
        tests.create_tokens_acl(self.session)
Pierre-Yves Chibon 73d120
        self.create_project_full("clonetest", {"create_readme": "y"})
Patrick Uiterwijk a50651
Patrick Uiterwijk a50651
        # Verify the new project is indeed on repoSpanner
Pierre-Yves Chibon 73d120
        project = pagure.lib.query._get_project(self.session, "clonetest")
Patrick Uiterwijk a50651
        self.assertTrue(project.is_on_repospanner)
Patrick Uiterwijk a50651
Patrick Uiterwijk a50651
        # Unfortunately, actually testing a git clone would need the app to
Patrick Uiterwijk a50651
        # run on a TCP port, which the test environment doesn't do.
Pierre-Yves Chibon 73d120
        output = self.app.get(
Pierre-Yves Chibon 73d120
            "/clonetest.git/info/refs?service=git-upload-pack"
Pierre-Yves Chibon 73d120
        )
Patrick Uiterwijk a50651
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 73d120
        self.assertEqual(
Pierre-Yves Chibon 73d120
            output.content_type, "application/x-git-upload-pack-advertisement"
Pierre-Yves Chibon 73d120
        )
Patrick Uiterwijk a50651
        output_text = output.get_data(as_text=True)
Patrick Uiterwijk a50651
        self.assertIn("# service=git-upload-pack", output_text)
Patrick Uiterwijk 05f1d9
        self.assertIn("agent=repoSpanner", output_text)
Patrick Uiterwijk a50651
        self.assertIn("symref=HEAD:refs/heads/master", output_text)
Patrick Uiterwijk a50651
        self.assertIn(" refs/heads/master\x00", output_text)
Patrick Uiterwijk a50651
Patrick Uiterwijk 802c7e
        output = self.app.post(
Pierre-Yves Chibon 73d120
            "/clonetest.git/git-upload-pack",
Pierre-Yves Chibon 73d120
            headers={"Content-Type": "application/x-git-upload-pack-request"},
Patrick Uiterwijk 802c7e
        )
Patrick Uiterwijk 4e180b
        self.assertEqual(output.status_code, 400)
Patrick Uiterwijk 802c7e
        output_text = output.get_data(as_text=True)
Patrick Uiterwijk 802c7e
        self.assertIn("Error processing your request", output_text)
Patrick Uiterwijk 802c7e
Patrick Uiterwijk 69ea3d
    @print_repospanner_log
Pierre-Yves Chibon 73d120
    @patch.dict(
Pierre-Yves Chibon 73d120
        "pagure.config.config",
Pierre-Yves Chibon 73d120
        {
Pierre-Yves Chibon 73d120
            "ALLOW_HTTP_PULL_PUSH": True,
Pierre-Yves Chibon 73d120
            "ALLOW_HTTP_PUSH": True,
Pierre-Yves Chibon 73d120
            "HTTP_REPO_ACCESS_GITOLITE": False,
Pierre-Yves Chibon 73d120
        },
Pierre-Yves Chibon 73d120
    )
Patrick Uiterwijk a50651
    def test_http_push(self):
Patrick Uiterwijk a50651
        """ Test that the HTTP push endpoint works for repoSpanner. """
Patrick Uiterwijk a50651
        tests.create_projects(self.session)
Patrick Uiterwijk a50651
        tests.create_tokens(self.session)
Patrick Uiterwijk a50651
        tests.create_tokens_acl(self.session)
Pierre-Yves Chibon 73d120
        self.create_project_full("clonetest", {"create_readme": "y"})
Patrick Uiterwijk a50651
Patrick Uiterwijk a50651
        # Verify the new project is indeed on repoSpanner
Pierre-Yves Chibon 73d120
        project = pagure.lib.query._get_project(self.session, "clonetest")
Patrick Uiterwijk a50651
        self.assertTrue(project.is_on_repospanner)
Patrick Uiterwijk a50651
Patrick Uiterwijk a50651
        # Unfortunately, actually testing a git clone would need the app to
Patrick Uiterwijk a50651
        # run on a TCP port, which the test environment doesn't do.
Patrick Uiterwijk a50651
        output = self.app.get(
Pierre-Yves Chibon 73d120
            "/clonetest.git/info/refs?service=git-receive-pack",
Pierre-Yves Chibon 73d120
            environ_overrides={"REMOTE_USER": "pingou"},
Patrick Uiterwijk a50651
        )
Patrick Uiterwijk a50651
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 73d120
        self.assertEqual(
Pierre-Yves Chibon 73d120
            output.content_type, "application/x-git-receive-pack-advertisement"
Pierre-Yves Chibon 73d120
        )
Patrick Uiterwijk a50651
        output_text = output.get_data(as_text=True)
Patrick Uiterwijk 05f1d9
        self.assertIn("# service=git-receive-pack", output_text)
Patrick Uiterwijk 05f1d9
        self.assertIn("agent=repoSpanner", output_text)
Patrick Uiterwijk a50651
        self.assertIn("symref=HEAD:refs/heads/master", output_text)
Patrick Uiterwijk a50651
        self.assertIn(" refs/heads/master\x00", output_text)
Patrick Uiterwijk a50651
Patrick Uiterwijk 69ea3d
    @print_repospanner_log
Pierre-Yves Chibon 73d120
    @patch("pagure.ui.app.admin_session_timedout")
Patrick Uiterwijk d29158
    def test_hooks(self, ast):
Patrick Uiterwijk d29158
        """ Test hook setting and running works. """
Patrick Uiterwijk d29158
        ast.return_value = False
Patrick Uiterwijk d29158
        pagure.cli.admin.session = self.session
Patrick Uiterwijk d29158
Pierre-Yves Chibon 73d120
        user = tests.FakeUser(username="foo")
Patrick Uiterwijk d29158
        with tests.user_set(self.app.application, user):
Patrick Uiterwijk d29158
            data = {
Pierre-Yves Chibon 73d120
                "name": "project-1",
Pierre-Yves Chibon 73d120
                "description": "Project #1",
Pierre-Yves Chibon 73d120
                "create_readme": "y",
Pierre-Yves Chibon 73d120
                "csrf_token": self.get_csrf(),
Patrick Uiterwijk d29158
            }
Patrick Uiterwijk d29158
Pierre-Yves Chibon 73d120
            output = self.app.post("/new/", data=data, follow_redirects=True)
Patrick Uiterwijk d29158
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk d29158
            output_text = output.get_data(as_text=True)
Patrick Uiterwijk d29158
            self.assertIn(
Pierre-Yves Chibon 73d120
                '
\nProject #1', output_text
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk d29158
            self.assertIn(
Pierre-Yves Chibon 73d120
                "<title>Overview - project-1 - Pagure</title>", output_text
Pierre-Yves Chibon 73d120
            )
Pierre-Yves Chibon 73d120
            self.assertIn("Added the README", output_text)
Patrick Uiterwijk d29158
Pierre-Yves Chibon 73d120
            output = self.app.get("/project-1/settings")
Patrick Uiterwijk d29158
            self.assertIn(
Pierre-Yves Chibon 73d120
                "This repository is on repoSpanner region default",
Pierre-Yves Chibon 73d120
                output.get_data(as_text=True),
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
            # Check file before the commit:
Pierre-Yves Chibon 73d120
            output = self.app.get("/project-1/raw/master/f/README.md")
Patrick Uiterwijk d29158
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk d29158
            output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 73d120
            self.assertEqual(output_text, "# project-1\n\nProject #1")
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
        with tests.user_set(self.app.application, user):
Patrick Uiterwijk d29158
            # Set editing Denied
Patrick Uiterwijk d29158
            self.set_auth_status(False)
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
            # Try to make an edit in the repo
Patrick Uiterwijk d29158
            data = {
Pierre-Yves Chibon 73d120
                "content": "foo\n bar\n  baz",
Pierre-Yves Chibon 73d120
                "commit_title": "test commit",
Pierre-Yves Chibon 73d120
                "commit_message": "Online commit",
Pierre-Yves Chibon 73d120
                "email": "foo@bar.com",
Pierre-Yves Chibon 73d120
                "branch": "master",
Pierre-Yves Chibon 73d120
                "csrf_token": self.get_csrf(),
Patrick Uiterwijk d29158
            }
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
            output = self.app.post(
Pierre-Yves Chibon 73d120
                "/project-1/edit/master/f/README.md",
Pierre-Yves Chibon 73d120
                data=data,
Pierre-Yves Chibon 73d120
                follow_redirects=True,
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk d29158
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk d29158
            output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 73d120
            self.assertIn("Remote hook declined the push: ", output_text)
Patrick Uiterwijk d29158
            self.assertIn(
Patrick Uiterwijk 7262c5
                "Denied push for ref 'refs/heads/master' for user 'foo'",
Pierre-Yves Chibon 73d120
                output_text,
Patrick Uiterwijk d29158
            )
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
            # Check file after the commit:
Pierre-Yves Chibon 73d120
            output = self.app.get("/project-1/raw/master/f/README.md")
Patrick Uiterwijk d29158
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk d29158
            output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 73d120
            self.assertEqual(output_text, "# project-1\n\nProject #1")
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
            # Set editing Allowed
Patrick Uiterwijk d29158
            self.set_auth_status(True)
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
            # Try to make an edit in the repo
Patrick Uiterwijk d29158
            data = {
Pierre-Yves Chibon 73d120
                "content": "foo\n bar\n  baz",
Pierre-Yves Chibon 73d120
                "commit_title": "test commit",
Pierre-Yves Chibon 73d120
                "commit_message": "Online commit",
Pierre-Yves Chibon 73d120
                "email": "foo@bar.com",
Pierre-Yves Chibon 73d120
                "branch": "master",
Pierre-Yves Chibon 73d120
                "csrf_token": self.get_csrf(),
Patrick Uiterwijk d29158
            }
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
            output = self.app.post(
Pierre-Yves Chibon 73d120
                "/project-1/edit/master/f/README.md",
Pierre-Yves Chibon 73d120
                data=data,
Pierre-Yves Chibon 73d120
                follow_redirects=True,
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk d29158
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk d29158
            output_text = output.get_data(as_text=True)
Patrick Uiterwijk d29158
            self.assertIn(
Pierre-Yves Chibon 73d120
                "<title>Commits - project-1 - Pagure</title>", output_text
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk d29158
Patrick Uiterwijk d29158
            # Check file after the commit:
Pierre-Yves Chibon 73d120
            output = self.app.get("/project-1/raw/master/f/README.md")
Patrick Uiterwijk d29158
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk d29158
            output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 73d120
            self.assertEqual(output_text, "foo\n bar\n  baz")
Patrick Uiterwijk d29158
Patrick Uiterwijk 69ea3d
    @print_repospanner_log
Pierre-Yves Chibon 73d120
    @patch.dict(
Pierre-Yves Chibon 73d120
        "pagure.config.config",
Pierre-Yves Chibon 73d120
        {
Pierre-Yves Chibon 73d120
            "PAGURE_ADMIN_USERS": ["pingou"],
Pierre-Yves Chibon 73d120
            "ALLOW_ADMIN_IGNORE_EXISTING_REPOS": True,
Pierre-Yves Chibon 73d120
        },
Pierre-Yves Chibon 73d120
    )
Pierre-Yves Chibon 73d120
    @patch("pagure.ui.app.admin_session_timedout")
Patrick Uiterwijk 335383
    def test_adopt_project(self, ast):
Patrick Uiterwijk 335383
        """ Test adopting a project in repoSpanner works. """
Patrick Uiterwijk 335383
        ast.return_value = False
Patrick Uiterwijk 335383
Pierre-Yves Chibon 73d120
        user = tests.FakeUser(username="foo")
Patrick Uiterwijk 335383
        with tests.user_set(self.app.application, user):
Pierre-Yves Chibon 73d120
            output = self.app.get("/new/")
Patrick Uiterwijk 335383
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk 335383
            output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 73d120
            self.assertIn("Create new Project", output_text)
Patrick Uiterwijk 335383
Patrick Uiterwijk 335383
            data = {
Pierre-Yves Chibon 73d120
                "name": "project-1",
Pierre-Yves Chibon 73d120
                "description": "Project #1",
Pierre-Yves Chibon 73d120
                "create_readme": "y",
Pierre-Yves Chibon 73d120
                "csrf_token": self.get_csrf(),
Patrick Uiterwijk 335383
            }
Patrick Uiterwijk 335383
Pierre-Yves Chibon 73d120
            output = self.app.post("/new/", data=data, follow_redirects=True)
Patrick Uiterwijk 335383
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk 335383
            output_text = output.get_data(as_text=True)
Patrick Uiterwijk 335383
            self.assertIn(
Pierre-Yves Chibon 73d120
                '
\nProject #1', output_text
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 335383
            self.assertIn(
Pierre-Yves Chibon 73d120
                "<title>Overview - project-1 - Pagure</title>", output_text
Pierre-Yves Chibon 73d120
            )
Pierre-Yves Chibon 73d120
            self.assertIn("Added the README", output_text)
Patrick Uiterwijk 335383
Pierre-Yves Chibon 73d120
            output = self.app.get("/project-1/settings")
Patrick Uiterwijk 335383
            self.assertIn(
Pierre-Yves Chibon 73d120
                "This repository is on repoSpanner region default",
Pierre-Yves Chibon 73d120
                output.get_data(as_text=True),
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 335383
Patrick Uiterwijk 335383
        # Delete the project instance so that the actual repo remains
Pierre-Yves Chibon 73d120
        project = pagure.lib.query._get_project(self.session, "project-1")
Patrick Uiterwijk 335383
        self.session.delete(project)
Patrick Uiterwijk 335383
        self.session.commit()
Pierre-Yves Chibon 73d120
        shutil.rmtree(os.path.join(self.path, "repos", "pseudo"))
Patrick Uiterwijk 335383
Pierre-Yves Chibon 73d120
        user = tests.FakeUser(username="pingou")
Patrick Uiterwijk 335383
        with tests.user_set(self.app.application, user):
Pierre-Yves Chibon 73d120
            output = self.app.get("/project-1/")
Patrick Uiterwijk 335383
            self.assertEqual(output.status_code, 404)
Patrick Uiterwijk 335383
Patrick Uiterwijk 335383
            data = {
Pierre-Yves Chibon 73d120
                "name": "project-1",
Pierre-Yves Chibon 73d120
                "description": "Recreated project #1",
Pierre-Yves Chibon 73d120
                "create_readme": "false",
Pierre-Yves Chibon 73d120
                "csrf_token": self.get_csrf(),
Patrick Uiterwijk 335383
            }
Pierre-Yves Chibon 73d120
            output = self.app.post("/new/", data=data, follow_redirects=True)
Patrick Uiterwijk 335383
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk 335383
            output_text = output.get_data(as_text=True)
Patrick Uiterwijk 335383
            self.assertIn(
Pierre-Yves Chibon 73d120
                "Repo pagure/main/project-1 already exists", output_text
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 335383
Pierre-Yves Chibon 73d120
            data["ignore_existing_repos"] = "y"
Pierre-Yves Chibon 73d120
            output = self.app.post("/new/", data=data, follow_redirects=True)
Patrick Uiterwijk 335383
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk 335383
            output_text = output.get_data(as_text=True)
Patrick Uiterwijk 335383
            self.assertIn(
Patrick Uiterwijk 335383
                '
\nRecreated project #1',
Pierre-Yves Chibon 73d120
                output_text,
Pierre-Yves Chibon 73d120
            )
Patrick Uiterwijk 335383
            self.assertIn(
Pierre-Yves Chibon 73d120
                "<title>Overview - project-1 - Pagure</title>", output_text
Pierre-Yves Chibon 73d120
            )
Pierre-Yves Chibon 73d120
            self.assertIn("Added the README", output_text)
Patrick Uiterwijk 335383
Patrick Uiterwijk 3f97f6
Pierre-Yves Chibon 73d120
if __name__ == "__main__":
Patrick Uiterwijk 3f97f6
    unittest.main(verbosity=2)