summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2025-03-21 17:37:41 +0000
committerCoprDistGit <infra@openeuler.org>2025-03-21 17:37:42 +0000
commit133ef9d4cb72a5081fab588e821eee4a178afc7e (patch)
tree76779ef5ca00cab259eb516c4c44eef0b3048cc9
parentc3bf05eae09a01b1153504b7e7de2b8c43a34eea (diff)
automatic import of copr-backend
-rw-r--r--copr-backend.spec15
-rw-r--r--euler_msgbus.patch4
-rw-r--r--fail_to_build_in_oe2403.patch14
-rw-r--r--helpers.patch35
-rw-r--r--print_queues.patch12
-rw-r--r--sources4
-rw-r--r--support_signatrust_backend.patch505
7 files changed, 440 insertions, 149 deletions
diff --git a/copr-backend.spec b/copr-backend.spec
index 511f185..ae9f5f4 100644
--- a/copr-backend.spec
+++ b/copr-backend.spec
@@ -1,11 +1,11 @@
%global prunerepo_version 1.20
-%global tests_version 2
+%global tests_version 5
%global tests_tar test-data-copr-backend
-%global copr_common_version 0.19
+%global copr_common_version 0.20.1.dev1
Name: copr-backend
-Version: 1.168
+Version: 1.173
Release: 1%{?dist}
Summary: Backend for Copr
@@ -17,9 +17,9 @@ URL: https://github.com/fedora-copr/copr
# tito build --tgz --tag %%name-%%version-%%release
Source0: %{name}-%{version}.tar.gz
Source1: %{tests_tar}-%{tests_version}.tar.gz
-Patch1: helpers.patch
+Patch1: fail_to_build_in_oe2403.patch
Patch2: euler_msgbus.patch
-Patch3: print_queues.patch
+#Patch3: print_queues.patch
#Patch4: redis_helpers.patch # should patch to copr common
Patch5: support_signatrust_backend.patch
Patch6: signatrust_bin.patch
@@ -39,6 +39,7 @@ BuildRequires: python3-devel
BuildRequires: python3-setuptools
BuildRequires: python3-copr
+BuildRequires: python3-kafka-python
BuildRequires: python3-copr-common = %copr_common_version
BuildRequires: python3-daemon
BuildRequires: python3-dateutil
@@ -103,6 +104,7 @@ Requires: rsync
Requires: modulemd-tools >= 0.6
Recommends: util-linux-core
Requires: zstd
+Requires: python3-kafka-python
Requires(post): systemd
Requires(preun): systemd
@@ -177,7 +179,6 @@ install -d %{buildroot}%{_sysconfdir}/logstash.d
install -d %{buildroot}%{_datadir}/logstash/patterns/
cp -a conf/logstash/lighttpd.pattern %{buildroot}%{_datadir}/logstash/patterns/lighttpd.pattern
-cp -a conf/playbooks %{buildroot}%{_pkgdocdir}/
install -d %{buildroot}%{_pkgdocdir}/examples/%{_sysconfdir}/logstash.d
cp -a conf/logstash/copr_backend.conf %{buildroot}%{_pkgdocdir}/examples/%{_sysconfdir}/logstash.d/copr_backend.conf
@@ -221,7 +222,6 @@ useradd -r -g copr -G lighttpd -s /bin/bash -c "COPR user" copr
%config(noreplace) %{_sysconfdir}/logrotate.d/copr-backend
%dir %{_pkgdocdir}
%doc %{_pkgdocdir}/lighttpd
-%doc %{_pkgdocdir}/playbooks
%dir %{_sysconfdir}/copr
%config(noreplace) %attr(0640, root, copr) %{_sysconfdir}/copr/copr-be.conf
%{_unitdir}/*.service
@@ -242,7 +242,6 @@ useradd -r -g copr -G lighttpd -s /bin/bash -c "COPR user" copr
%doc
%{_pkgdocdir}/
%exclude %{_pkgdocdir}/lighttpd
-%exclude %{_pkgdocdir}/playbooks
%changelog
* Wed Mar 12 2025 lichaoran <pkwarcraft@hotmail.com> 1.168-1
diff --git a/euler_msgbus.patch b/euler_msgbus.patch
index 8973ce1..5eca90a 100644
--- a/euler_msgbus.patch
+++ b/euler_msgbus.patch
@@ -1,8 +1,8 @@
-diff --git a/backend/copr_backend/euler_msgbus.py b/backend/copr_backend/euler_msgbus.py
+diff --git a/copr_backend/euler_msgbus.py b/copr_backend/euler_msgbus.py
new file mode 100644
index 000000000..1395249be
--- /dev/null
-+++ b/backend/copr_backend/euler_msgbus.py
++++ b/copr_backend/euler_msgbus.py
@@ -0,0 +1,77 @@
+import socket
+
diff --git a/fail_to_build_in_oe2403.patch b/fail_to_build_in_oe2403.patch
new file mode 100644
index 0000000..be32aee
--- /dev/null
+++ b/fail_to_build_in_oe2403.patch
@@ -0,0 +1,14 @@
+diff --git a/tests/test_modifyrepo.py b/backend/tests/test_modifyrepo.py
+index 330ff68f7..2c1bd0a66 100644
+--- a/tests/test_modifyrepo.py
++++ b/tests/test_modifyrepo.py
+@@ -431,7 +431,8 @@ def test_copr_repo_run_createrepo(self, popen, do_stat, chroot, database_option)
+ "--workers", "8", "--general-compress-type=gz", "--update"] + additional_args
+
+ @pytest.mark.skipif(
+- distro.id() == 'fedora' and int(distro.version()) >= 36,
++ (distro.id() == 'fedora' and int(distro.version()) >= 36) or
++ (distro.id() == 'openeuler' and float(distro.version()) >= 24.03),
+ reason="createrepo_c dropped md5 checksum support"
+ )
+ def test_copr_repo_el5(self, f_third_build):
diff --git a/helpers.patch b/helpers.patch
deleted file mode 100644
index 33be500..0000000
--- a/helpers.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-diff --git a/copr_backend/helpers.py b/copr_backend/helpers.py
-index df2819e0..c85c7396 100644
---- a/copr_backend/helpers.py
-+++ b/copr_backend/helpers.py
-@@ -288,6 +288,9 @@ class BackendConfigReader(object):
- opts.redis_port = _get_conf(
- cp, "backend", "redis_port", "6379")
-
-+ opts.redis_pwd = _get_conf(
-+ cp, "backend", "redis_password", None)
-+
- opts.redis_db = _get_conf(
- cp, "backend", "redis_db", "0")
-
-
-@@ -416,6 +416,19 @@ class BackendConfigReader(object):
- opts.aws_cloudfront_distribution = _get_conf(
- cp, "backend", "aws_cloudfront_distribution", None)
-
-+ opts.message = Munch()
-+ opts.message.bootstrap_servers = _get_conf(
-+ cp, "message", "bootstrap_servers", None)
-+
-+ opts.message.user_name = _get_conf(
-+ cp, "message", "user_name", None)
-+
-+ opts.message.password = _get_conf(
-+ cp, "message", "password", None)
-+
-+ opts.message.topic = _get_conf(
-+ cp, "message", "topic", None)
-+
- # ssh options
- opts.ssh = Munch()
- opts.ssh.builder_config = _get_conf(
diff --git a/print_queues.patch b/print_queues.patch
deleted file mode 100644
index 83d7fc8..0000000
--- a/print_queues.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/run/print_queues.py b/run/print_queues.py
-index 849f8f6a..f48d1157 100755
---- a/run/print_queues.py
-+++ b/run/print_queues.py
-@@ -14,6 +14,7 @@ redis_config = {
- 'host': opts['redis_host'],
- 'port': opts['redis_port'],
- 'db': opts['redis_db'],
-+ 'password': opts['redis_pwd'],
- }
-
- for i in range(0, NUM_QUEUES):
diff --git a/sources b/sources
index 704becb..adc3d34 100644
--- a/sources
+++ b/sources
@@ -1,2 +1,2 @@
-8dacd18f46475296d0199365db977649 copr-backend-1.168.tar.gz
-a35697a68640fb4c0bcfef02a93eac63 test-data-copr-backend-2.tar.gz
+5ed3646f3887a4ff1656c1f7a05d78eb copr-backend-1.173.tar.gz
+c94d55e21a4935b3e62f673fbae65af2 test-data-copr-backend-5.tar.gz
diff --git a/support_signatrust_backend.patch b/support_signatrust_backend.patch
index 9e1fde5..d803d26 100644
--- a/support_signatrust_backend.patch
+++ b/support_signatrust_backend.patch
@@ -1,5 +1,5 @@
-diff --git a/copr_backend/actions.py b/copr_backend/actions.py
-index 39722b84..6da2dfb6 100644
+diff --git a/copr_backend/actions.py b/backend/copr_backend/actions.py
+index 39722b843..6da2dfb65 100644
--- a/copr_backend/actions.py
+++ b/copr_backend/actions.py
@@ -21,13 +21,13 @@ from copr_common.worker_manager import WorkerManager
@@ -57,8 +57,8 @@ index 39722b84..6da2dfb6 100644
chroot, opts=self.opts, log=self.log)
self.log.info("Forked build %s as %s", src_path, dst_path)
-diff --git a/copr_backend/background_worker.py b/copr_backend/background_worker.py
-index 4b5f1313..bc05edbd 100644
+diff --git a/copr_backend/background_worker.py b/backend/copr_backend/background_worker.py
+index 4b5f13135..bc05edbd7 100644
--- a/copr_backend/background_worker.py
+++ b/copr_backend/background_worker.py
@@ -9,7 +9,7 @@ import logging
@@ -78,21 +78,22 @@ index 4b5f1313..bc05edbd 100644
def _switch_logger_to_redis(self):
logger_name = '{}.{}.pid-{}'.format(
-diff --git a/copr_backend/background_worker_build.py b/copr_backend/background_worker_build.py
-index 233549b4..afc948e8 100644
+diff --git a/copr_backend/background_worker_build.py b/backend/copr_backend/background_worker_build.py
+index 0eee39ab8..c12d4921d 100644
--- a/copr_backend/background_worker_build.py
+++ b/copr_backend/background_worker_build.py
-@@ -27,7 +27,7 @@ from copr_backend.helpers import (
+@@ -27,8 +27,8 @@ from copr_backend.helpers import (
+ call_copr_repo, run_cmd, register_build_result, format_evr,
)
from copr_backend.job import BuildJob
-from copr_backend.msgbus import MessageSender
-+from copr_backend.euler_msgbus import MessageSender
-from copr_backend.sign import sign_rpms_in_dir, get_pubkey
++from copr_backend.euler_msgbus import MessageSender
+from copr_backend.sign import new_signer
from copr_backend.sshcmd import SSHConnection, SSHConnectionError
from copr_backend.vm_alloc import ResallocHostFactory
-@@ -599,7 +599,7 @@ class BuildBackgroundWorker(BackendBackgroundWorker):
+@@ -622,7 +622,7 @@ class BuildBackgroundWorker(BackendBackgroundWorker):
self.log.info("Going to sign pkgs from source: %s in chroot: %s",
self.job.task_id, self.job.chroot_dir)
@@ -101,7 +102,7 @@ index 233549b4..afc948e8 100644
self.job.project_owner,
self.job.project_name,
os.path.join(self.job.chroot_dir, self.job.target_dir_name),
-@@ -712,7 +712,7 @@ class BuildBackgroundWorker(BackendBackgroundWorker):
+@@ -736,7 +736,7 @@ class BuildBackgroundWorker(BackendBackgroundWorker):
# TODO: uncomment this when key revoke/change will be implemented
# if os.path.exists(pubkey_path):
# return
@@ -110,8 +111,8 @@ index 233549b4..afc948e8 100644
self.log.info("Added pubkey for user %s project %s into: %s",
user, project, pubkey_path)
-diff --git a/copr_backend/constants.py b/copr_backend/constants.py
-index a529be28..83bcb8fb 100644
+diff --git a/copr_backend/constants.py b/backend/copr_backend/constants.py
+index a529be28a..83bcb8fbe 100644
--- a/copr_backend/constants.py
+++ b/copr_backend/constants.py
@@ -13,6 +13,7 @@ DEF_BUILD_USER = "mockbuilder"
@@ -122,8 +123,8 @@ index a529be28..83bcb8fb 100644
DEF_CONSECUTIVE_FAILURE_THRESHOLD = 10
-diff --git a/copr_backend/exceptions.py b/copr_backend/exceptions.py
-index 21afb14c..0865fcc8 100644
+diff --git a/copr_backend/exceptions.py b/backend/copr_backend/exceptions.py
+index 21afb14c6..0865fcc8c 100644
--- a/copr_backend/exceptions.py
+++ b/copr_backend/exceptions.py
@@ -48,8 +48,8 @@ class CoprKeygenRequestError(Exception):
@@ -137,8 +138,8 @@ index 21afb14c..0865fcc8 100644
out += "status code: {}\n" "response content: {}\n" \
.format(self.response.status_code, self.response.content)
return out
-diff --git a/copr_backend/helpers.py b/copr_backend/helpers.py
-index 05348366..db4af7f4 100644
+diff --git a/copr_backend/helpers.py b/backend/copr_backend/helpers.py
+index 75fa5e62d..291228912 100644
--- a/copr_backend/helpers.py
+++ b/copr_backend/helpers.py
@@ -31,7 +31,7 @@ from munch import Munch
@@ -147,7 +148,7 @@ index 05348366..db4af7f4 100644
from copr_backend.constants import DEF_BUILD_USER, DEF_BUILD_TIMEOUT, DEF_CONSECUTIVE_FAILURE_THRESHOLD, \
- CONSECUTIVE_FAILURE_REDIS_KEY, default_log_format
+ CONSECUTIVE_FAILURE_REDIS_KEY, default_log_format, DEF_SIGN_BACKEND
- from copr_backend.exceptions import CoprBackendError, CoprBackendSrpmError
+ from copr_backend.exceptions import CoprBackendError
from . import constants
@@ -309,6 +309,18 @@ class BackendConfigReader(object):
@@ -169,32 +170,11 @@ index 05348366..db4af7f4 100644
opts.build_groups = []
for group_id in range(opts.build_groups_count):
archs = _get_conf(cp, "backend",
-diff --git a/copr_backend/sign.py b/copr_backend/sign.py
-index 6655fb98..31af3c8a 100644
+diff --git a/copr_backend/sign.py b/backend/copr_backend/sign.py
+index e21653e78..95f674255 100644
--- a/copr_backend/sign.py
+++ b/copr_backend/sign.py
-@@ -4,8 +4,11 @@
- Wrapper for /bin/sign from obs-sign package
- """
-
-+from datetime import datetime, timedelta, timezone
- from subprocess import Popen, PIPE, SubprocessError
- import os
-+import re
-+import requests
- import time
-
- from packaging import version
-@@ -16,8 +19,6 @@ from .exceptions import CoprSignError, CoprSignNoKeyError, \
- CoprKeygenRequestError
-
-
--SIGN_BINARY = "/bin/sign"
--
- def create_gpg_email(username, projectname, domain):
- """
- Creates canonical name_email to identify gpg key
-@@ -25,78 +26,6 @@ def create_gpg_email(username, projectname, domain):
+@@ -25,78 +25,6 @@ def create_gpg_email(username, projectname, domain):
return "{}#{}@copr.{}".format(username, projectname, domain)
@@ -273,56 +253,63 @@ index 6655fb98..31af3c8a 100644
def gpg_hashtype_for_chroot(chroot, opts):
"""
Given the chroot name (in "mock format", like "fedora-rawhide-x86_64")
-@@ -135,133 +64,438 @@ def gpg_hashtype_for_chroot(chroot, opts):
- # fallback to sha256
+@@ -136,133 +64,436 @@ def gpg_hashtype_for_chroot(chroot, opts):
return "sha256"
+
+-def sign_rpms_in_dir(username, projectname, path, chroot, opts, log):
+- """
+- Signs rpms using obs-signd.
+# a sign interface
+class Signer(object):
+ @classmethod
+ def get_pubkey(cls, username, projectname, log, sign_domain, outfile=None):
+ """get public key"""
+ raise NotImplementedError
-+
+
+- If some some pkgs failed to sign, entire build marked as failed,
+- but we continue to try sign other pkgs.
+ @classmethod
+ def sign_rpms_in_dir(cls, username, projectname, path, chroot, opts, log):
+ """batch sign rpms"""
+ raise NotImplementedError
-+
+
+- :param username: copr username
+- :param projectname: copr projectname
+- :param path: directory with rpms to be signed
+- :param chroot: chroot name where we sign packages, affects the hash type
+- :param Munch opts: backend config
+ @classmethod
-+ def create_user_keys(cls, username, projectname, opts):
++ def create_user_keys(username, projectname, opts, try_indefinitely=False):
+ """create user key pair"""
+ raise NotImplementedError
-+
+
+- :type log: logging.Logger
+ @classmethod
+ def _sign_one(cls, path, email, hashtype, log):
+ """sign one rpm"""
+ raise NotImplementedError
-+
+
+- :raises: :py:class:`backend.exceptions.CoprSignError` failed to sign at least one package
+- """
+ @classmethod
+ def _unsign_one(cls, path):
+ # Requires rpm-sign package
+ cmd = ["/usr/bin/rpm", "--delsign", path]
+ handle = Popen(cmd, stdout=PIPE, stderr=PIPE, encoding="utf-8")
+ stdout, stderr = handle.communicate()
-
--def sign_rpms_in_dir(username, projectname, path, chroot, opts, log):
-- """
-- Signs rpms using obs-signd.
--
-- If some some pkgs failed to sign, entire build marked as failed,
-- but we continue to try sign other pkgs.
++
+ if handle.returncode != 0:
+ err = CoprSignError(
+ msg="Failed to unsign {}".format(path),
+ return_code=handle.returncode,
+ cmd=cmd, stdout=stdout, stderr=stderr)
-- :param username: copr username
-- :param projectname: copr projectname
-- :param path: directory with rpms to be signed
-- :param chroot: chroot name where we sign packages, affects the hash type
-- :param Munch opts: backend config
+- rpm_list = [
+- os.path.join(path, filename)
+- for filename in os.listdir(path)
+- if filename.endswith(".rpm")
+- ]
+ raise err
+
+ return stdout, stderr
@@ -377,25 +364,22 @@ index 6655fb98..31af3c8a 100644
+ if filename.endswith(".rpm")
+ ]
-- :type log: logging.Logger
+- if not rpm_list:
+- return
+ if not rpm_list:
+ return
-- :raises: :py:class:`backend.exceptions.CoprSignError` failed to sign at least one package
-- """
-- rpm_list = [
-- os.path.join(path, filename)
-- for filename in os.listdir(path)
-- if filename.endswith(".rpm")
-- ]
+- hashtype = gpg_hashtype_for_chroot(chroot, opts)
+ hashtype = gpg_hashtype_for_chroot(chroot, opts)
-- if not rpm_list:
-- return
+- try:
+- get_pubkey(username, projectname, log, opts.sign_domain)
+- except CoprSignNoKeyError:
+- create_user_keys(username, projectname, opts, try_indefinitely=True)
+ try:
+ cls.get_pubkey(username, projectname, log, opts.sign_domain)
+ except CoprSignNoKeyError:
-+ cls.create_user_keys(username, projectname, opts)
++ cls.create_user_keys(username, projectname, opts, try_indefinitely=True)
+
+ errors = [] # tuples (rpm_filepath, exception)
+ for rpm in rpm_list:
@@ -444,14 +428,12 @@ index 6655fb98..31af3c8a 100644
+ .format([err[0] for err in errors]))
+
+def new_signer(opts):
-+ if opts.sign_backend == "obs-signd":
-+ return ObsSign
-+ elif opts.sign_backend == "signatrust":
++ if opts.sign_backend == "signatrust":
+ Signatrust.signatrust_token = opts.signatrust_token
+ Signatrust.signatrust_host = opts.signatrust_host
+ return Signatrust
-+ else:
-+ raise CoprSignError("invalid signer type: {}".format(opts.signer_type))
++ else: # keep obs-signd as default backend
++ return ObsSign
+
+class ObsSign(Signer):
+ sign_cmd = "/bin/sign"
@@ -484,19 +466,14 @@ index 6655fb98..31af3c8a 100644
+ return_code=returncode,
+ cmd=cmd, stdout=stdout, stderr=stderr)
-- hashtype = gpg_hashtype_for_chroot(chroot, opts)
+- errors = [] # tuples (rpm_filepath, exception)
+- for rpm in rpm_list:
+ if outfile:
+ with open(outfile, "w") as handle:
+ handle.write(stdout)
-
-- try:
-- get_pubkey(username, projectname, log, opts.sign_domain)
-- except CoprSignNoKeyError:
-- create_user_keys(username, projectname, opts)
++
+ return stdout
-
-- errors = [] # tuples (rpm_filepath, exception)
-- for rpm in rpm_list:
++
+ @classmethod
+ def _sign_one(cls, path, email, hashtype, log):
+ cmd = [cls.sign_cmd, "-4", "-h", hashtype, "-u", email, "-r", path]
@@ -509,7 +486,7 @@ index 6655fb98..31af3c8a 100644
+ return stdout, stderr
+
+ @classmethod
-+ def create_user_keys(cls, username, projectname, opts):
++ def create_user_keys(cls, username, projectname, opts, try_indefinitely=False):
+ """
+ Generate a new key-pair at sign host
+
@@ -528,7 +505,7 @@ index 6655fb98..31af3c8a 100644
+ keygen_url = "http://{}/gen_key".format(opts.keygen_host)
+ query = dict(url=keygen_url, data=data, method="post")
+ try:
-+ request = SafeRequest(log=log)
++ request = SafeRequest(log=log, try_indefinitely=try_indefinitely)
+ response = request.send(**query)
+ except Exception as e:
+ raise CoprKeygenRequestError(
@@ -673,7 +650,7 @@ index 6655fb98..31af3c8a 100644
+ """
+ check keyname existence
--def create_user_keys(username, projectname, opts):
+-def create_user_keys(username, projectname, opts, try_indefinitely=False):
- """
- Generate a new key-pair at sign host
+ HEAD /api/v1/keys/
@@ -697,7 +674,7 @@ index 6655fb98..31af3c8a 100644
- keygen_url = "http://{}/gen_key".format(opts.keygen_host)
- query = dict(url=keygen_url, data=data, method="post")
- try:
-- request = SafeRequest(log=log)
+- request = SafeRequest(log=log, try_indefinitely=try_indefinitely)
- response = request.send(**query)
- except Exception as e:
- raise CoprKeygenRequestError(
@@ -778,7 +755,7 @@ index 6655fb98..31af3c8a 100644
+ msg="Failed to check key existence", request="/api/v1/keys/name_identical", response=res)
+
+ @classmethod
-+ def create_user_keys(cls, username, projectname, opts):
++ def create_user_keys(cls, username, projectname, opts, try_indefinitely=False):
+ """
+ create user key pair
+
@@ -823,3 +800,351 @@ index 6655fb98..31af3c8a 100644
+ if res.status_code >= 400:
+ raise CoprKeygenRequestError(
+ msg="Failed to create user payload: {}".format(data), request="/api/v1/keys/", response=res)
+diff --git a/tests/daemons/test_log.py b/backend/tests/daemons/test_log.py
+index 73b1a777a..c68b7d918 100644
+--- a/tests/daemons/test_log.py
++++ b/tests/daemons/test_log.py
+@@ -45,7 +45,8 @@ class TestLog(object):
+ self.log_file = os.path.join(self.log_dir, "copr.log")
+ self.opts = Munch(
+ verbose=False,
+- log_dir=self.log_dir
++ log_dir=self.log_dir,
++ sign_backend = "obs-signd"
+ )
+ print("\n log dir: {}".format(self.log_dir))
+ self.queue = MagicMock()
+diff --git a/tests/daemons/unused_test_job_grab.py b/backend/tests/daemons/unused_test_job_grab.py
+index be3e64c56..79f6472b7 100644
+--- a/tests/daemons/unused_test_job_grab.py
++++ b/tests/daemons/unused_test_job_grab.py
+@@ -87,6 +87,7 @@ class TestJobGrab(object):
+ redis_host="127.0.0.1",
+ redis_port=6379,
+ redis_db=0,
++ sign_backend = "obs-signd"
+ )
+
+ self.queue = MagicMock()
+diff --git a/tests/run/test_copr_prune_results.py b/backend/tests/run/test_copr_prune_results.py
+index 6620f01b1..8c9ef2369 100644
+--- a/tests/run/test_copr_prune_results.py
++++ b/tests/run/test_copr_prune_results.py
+@@ -59,7 +59,8 @@ class TestPruneResults(object):
+ self.opts = Munch(
+ prune_days=14,
+ frontend_base_url = '<frontend_url>',
+- destdir=self.testresults_dir
++ destdir=self.testresults_dir,
++ sign_backend = "obs-signd"
+ )
+
+ def teardown_method(self, method):
+diff --git a/tests/test_action.py b/backend/tests/test_action.py
+index 7da3ab09c..4c935eb53 100644
+--- a/tests/test_action.py
++++ b/tests/test_action.py
+@@ -57,6 +57,7 @@ class TestAction(object):
+ results_baseurl=RESULTS_ROOT_URL,
+
+ do_sign=False,
++ sign_backend = "obs-signd",
+
+ keygen_host="example.com"
+ )
+@@ -136,7 +137,7 @@ class TestAction(object):
+ @mock.patch("copr_backend.actions.os.makedirs")
+ @mock.patch("copr_backend.actions.copy_tree")
+ @mock.patch("copr_backend.actions.os.path.exists")
+- @mock.patch("copr_backend.actions.unsign_rpms_in_dir")
++ @mock.patch("copr_backend.sign.ObsSign.unsign_rpms_in_dir")
+ @mock.patch("copr_backend.helpers.subprocess.Popen")
+ def test_action_handle_forks(self, mc_popen, mc_unsign_rpms_in_dir,
+ mc_exists, mc_copy_tree, _mc_os_makedirs,
+diff --git a/tests/test_background_worker_build.py b/backend/tests/test_background_worker_build.py
+index 1dfe19563..258564067 100644
+--- a/tests/test_background_worker_build.py
++++ b/tests/test_background_worker_build.py
+@@ -77,6 +77,7 @@ def _reset_build_worker():
+ # Don't waste time with mocking. We don't want to log anywhere, and we want
+ # to let BuildBackgroundWorker adjust the handlers.
+ worker.log.handlers = []
++ worker.opts.sign_backend = "obs-signd"
+ return worker
+
+ def _fake_host():
+diff --git a/tests/test_frontend.py b/backend/tests/test_frontend.py
+index eeb8dc8f4..06a6e605b 100644
+--- a/tests/test_frontend.py
++++ b/tests/test_frontend.py
+@@ -48,6 +48,7 @@ class TestFrontendClient(object):
+ self.opts = Munch(
+ frontend_base_url="http://example.com/",
+ frontend_auth="12345678",
++ sign_backend = "obs-signd"
+ )
+ self.fc = FrontendClient(self.opts)
+
+diff --git a/tests/test_helpers.py b/backend/tests/test_helpers.py
+index 8da70269d..e23565054 100644
+--- a/tests/test_helpers.py
++++ b/tests/test_helpers.py
+@@ -31,6 +31,7 @@ class TestHelpers(object):
+ self.opts = Munch(
+ redis_db=9,
+ redis_port=7777,
++ sign_backend = "obs-signd"
+ )
+
+ self.rc = get_redis_connection(self.opts)
+diff --git a/tests/test_sign.py b/backend/tests/test_sign.py
+index bf2dd1b8c..ebb8f2be3 100644
+--- a/tests/test_sign.py
++++ b/tests/test_sign.py
+@@ -10,10 +10,10 @@ import pytest
+
+ from copr_backend.exceptions import CoprSignError, CoprSignNoKeyError, CoprKeygenRequestError
+ from copr_backend.sign import (
+- get_pubkey, _sign_one, sign_rpms_in_dir, create_user_keys,
++ new_signer,
+ gpg_hashtype_for_chroot,
+- call_sign_bin,
+ )
++from copr_backend.constants import DEF_SIGN_BACKEND
+
+ STDOUT = "stdout"
+ STDERR = "stderr"
+@@ -33,6 +33,8 @@ class TestSign(object):
+ self.opts = Munch(keygen_host="example.com")
+ self.opts.gently_gpg_sha256 = False
+ self.opts.sign_domain = "fedorahosted.org"
++ self.opts.sign_backend = DEF_SIGN_BACKEND
++ self.signer = new_signer(self.opts)
+
+ def teardown_method(self, method):
+ if self.tmp_dir_path:
+@@ -60,7 +62,7 @@ class TestSign(object):
+ mc_handle.returncode = 0
+ mc_popen.return_value = mc_handle
+
+- result = get_pubkey(self.username, self.projectname, MagicMock(), self.opts.sign_domain)
++ result = self.signer.get_pubkey(self.username, self.projectname, MagicMock(), self.opts.sign_domain)
+ assert result == STDOUT
+ assert mc_popen.call_args[0][0] == ['/bin/sign', '-u', self.usermail, '-p']
+
+@@ -70,7 +72,7 @@ class TestSign(object):
+ mc_popen.side_effect = IOError(STDERR)
+
+ with pytest.raises(CoprSignError):
+- get_pubkey(self.username, self.projectname, MagicMock(), self.opts.sign_domain)
++ self.signer.get_pubkey(self.username, self.projectname, MagicMock(), self.opts.sign_domain)
+
+
+ @mock.patch("copr_backend.sign.time.sleep")
+@@ -82,7 +84,7 @@ class TestSign(object):
+ mc_popen.return_value = mc_handle
+
+ with pytest.raises(CoprSignNoKeyError) as err:
+- get_pubkey(self.username, self.projectname, MagicMock(), self.opts.sign_domain)
++ self.signer.get_pubkey(self.username, self.projectname, MagicMock(), self.opts.sign_domain)
+
+ assert "There are no gpg keys for user foo in keyring" in str(err)
+
+@@ -95,7 +97,7 @@ class TestSign(object):
+ mc_popen.return_value = mc_handle
+
+ with pytest.raises(CoprSignError) as err:
+- get_pubkey(self.username, self.projectname, MagicMock(), self.opts.sign_domain)
++ self.signer.get_pubkey(self.username, self.projectname, MagicMock(), self.opts.sign_domain)
+
+ assert "Failed to get user pubkey" in str(err)
+
+@@ -108,7 +110,7 @@ class TestSign(object):
+
+ outfile_path = os.path.join(self.tmp_dir_path, "out.pub")
+ assert not os.path.exists(outfile_path)
+- result = get_pubkey(self.username, self.projectname, MagicMock(),
++ result = self.signer.get_pubkey(self.username, self.projectname, MagicMock(),
+ self.opts.sign_domain, outfile_path)
+ assert result == STDOUT
+ assert os.path.exists(outfile_path)
+@@ -124,7 +126,7 @@ class TestSign(object):
+ mc_popen.return_value = mc_handle
+
+ fake_path = "/tmp/pkg.rpm"
+- result = _sign_one(fake_path, self.usermail, "sha1", MagicMock())
++ result = self.signer._sign_one(fake_path, self.usermail, "sha1", MagicMock())
+ assert STDOUT, STDERR == result
+
+ expected_cmd = ['/bin/sign', "-4", "-h", "sha1", "-u", self.usermail,
+@@ -137,7 +139,7 @@ class TestSign(object):
+
+ fake_path = "/tmp/pkg.rpm"
+ with pytest.raises(CoprSignError):
+- _sign_one(fake_path, self.usermail, "sha256", MagicMock())
++ self.signer._sign_one(fake_path, self.usermail, "sha256", MagicMock())
+
+ @mock.patch("copr_backend.sign.time.sleep")
+ @mock.patch("copr_backend.sign.Popen")
+@@ -149,12 +151,11 @@ class TestSign(object):
+
+ fake_path = "/tmp/pkg.rpm"
+ with pytest.raises(CoprSignError):
+- _sign_one(fake_path, self.usermail, "sha256", MagicMock())
++ self.signer._sign_one(fake_path, self.usermail, "sha256", MagicMock())
+
+- @staticmethod
+ @mock.patch("copr_backend.sign.time.sleep")
+ @mock.patch("copr_backend.sign.Popen")
+- def test_call_sign_bin_repeatedly(mc_popen, _sleep):
++ def test_call_sign_bin_repeatedly(self, mc_popen, _sleep):
+ """
+ Test that we attempt to run /bin/sign multiple times if it returns
+ non-zero exit status
+@@ -163,13 +164,13 @@ class TestSign(object):
+ mc_handle.communicate.return_value = (STDOUT, STDERR)
+ mc_handle.returncode = 1
+ mc_popen.return_value = mc_handle
+- call_sign_bin(cmd=[], log=MagicMock())
++ self.signer.call_sign_bin(cmd=[], log=MagicMock())
+ assert mc_popen.call_count == 3
+
+ @mock.patch("copr_backend.sign.SafeRequest.send")
+ def test_create_user_keys(self, mc_request):
+ mc_request.return_value.status_code = 200
+- create_user_keys(self.username, self.projectname, self.opts)
++ self.signer.create_user_keys(self.username, self.projectname, self.opts)
+
+ assert mc_request.called
+ expected_call = mock.call(
+@@ -183,7 +184,7 @@ class TestSign(object):
+ def test_create_user_keys_error_1(self, mc_request):
+ mc_request.side_effect = IOError()
+ with pytest.raises(CoprKeygenRequestError) as err:
+- create_user_keys(self.username, self.projectname, self.opts)
++ self.signer.create_user_keys(self.username, self.projectname, self.opts)
+
+ assert "Failed to create key-pair" in str(err)
+
+@@ -195,16 +196,16 @@ class TestSign(object):
+ mc_request.return_value.content = "error: {}".format(code)
+
+ with pytest.raises(CoprKeygenRequestError) as err:
+- create_user_keys(self.username, self.projectname, self.opts)
++ self.signer.create_user_keys(self.username, self.projectname, self.opts)
+ assert "Failed to create key-pair for user: foo, project:bar" in str(err)
+
+- @mock.patch("copr_backend.sign._sign_one")
+- @mock.patch("copr_backend.sign.create_user_keys")
+- @mock.patch("copr_backend.sign.get_pubkey")
++ @mock.patch("copr_backend.sign.ObsSign._sign_one")
++ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
++ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
+ def test_sign_rpms_id_dir_nothing(self, mc_gp, mc_cuk, mc_so,
+ tmp_dir):
+ # empty target dir doesn't produce error
+- sign_rpms_in_dir(self.username, self.projectname,
++ self.signer.sign_rpms_in_dir(self.username, self.projectname,
+ self.tmp_dir_path, "epel-8-x86_64", self.opts,
+ log=MagicMock())
+
+@@ -212,13 +213,13 @@ class TestSign(object):
+ assert not mc_cuk.called
+ assert not mc_so.called
+
+- @mock.patch("copr_backend.sign._sign_one")
+- @mock.patch("copr_backend.sign.create_user_keys")
+- @mock.patch("copr_backend.sign.get_pubkey")
++ @mock.patch("copr_backend.sign.ObsSign._sign_one")
++ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
++ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
+ def test_sign_rpms_id_dir_ok(self, mc_gp, mc_cuk, mc_so,
+ tmp_dir, tmp_files):
+
+- sign_rpms_in_dir(self.username, self.projectname,
++ self.signer.sign_rpms_in_dir(self.username, self.projectname,
+ self.tmp_dir_path, "fedora-rawhide-x86_64",
+ self.opts, log=MagicMock())
+
+@@ -234,15 +235,15 @@ class TestSign(object):
+ assert os.path.join(self.tmp_dir_path, name) in pathes
+ assert len(pathes) == count
+
+- @mock.patch("copr_backend.sign._sign_one")
+- @mock.patch("copr_backend.sign.create_user_keys")
+- @mock.patch("copr_backend.sign.get_pubkey")
++ @mock.patch("copr_backend.sign.ObsSign._sign_one")
++ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
++ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
+ def test_sign_rpms_id_dir_error_on_pubkey(
+ self, mc_gp, mc_cuk, mc_so, tmp_dir, tmp_files):
+
+ mc_gp.side_effect = CoprSignError("foobar")
+ with pytest.raises(CoprSignError):
+- sign_rpms_in_dir(self.username, self.projectname,
++ self.signer.sign_rpms_in_dir(self.username, self.projectname,
+ self.tmp_dir_path, "epel-7-x86_64", self.opts,
+ log=MagicMock())
+
+@@ -250,15 +251,15 @@ class TestSign(object):
+ assert not mc_cuk.called
+ assert not mc_so.called
+
+- @mock.patch("copr_backend.sign._sign_one")
+- @mock.patch("copr_backend.sign.create_user_keys")
+- @mock.patch("copr_backend.sign.get_pubkey")
++ @mock.patch("copr_backend.sign.ObsSign._sign_one")
++ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
++ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
+ def test_sign_rpms_id_dir_no_pub_key(
+ self, mc_gp, mc_cuk, mc_so, tmp_dir, tmp_files):
+
+ mc_gp.side_effect = CoprSignNoKeyError("foobar")
+
+- sign_rpms_in_dir(self.username, self.projectname,
++ self.signer.sign_rpms_in_dir(self.username, self.projectname,
+ self.tmp_dir_path, "rhel-7-x86_64", self.opts,
+ log=MagicMock())
+
+@@ -266,9 +267,9 @@ class TestSign(object):
+ assert mc_cuk.called
+ assert mc_so.called
+
+- @mock.patch("copr_backend.sign._sign_one")
+- @mock.patch("copr_backend.sign.create_user_keys")
+- @mock.patch("copr_backend.sign.get_pubkey")
++ @mock.patch("copr_backend.sign.ObsSign._sign_one")
++ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
++ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
+ def test_sign_rpms_id_dir_sign_error_one(
+ self, mc_gp, mc_cuk, mc_so, tmp_dir, tmp_files):
+
+@@ -276,7 +277,7 @@ class TestSign(object):
+ None, CoprSignError("foobar"), None
+ ]
+ with pytest.raises(CoprSignError):
+- sign_rpms_in_dir(self.username, self.projectname,
++ self.signer.sign_rpms_in_dir(self.username, self.projectname,
+ self.tmp_dir_path, "fedora-36-x86_64", self.opts,
+ log=MagicMock())
+
+@@ -285,15 +286,15 @@ class TestSign(object):
+
+ assert mc_so.called
+
+- @mock.patch("copr_backend.sign._sign_one")
+- @mock.patch("copr_backend.sign.create_user_keys")
+- @mock.patch("copr_backend.sign.get_pubkey")
++ @mock.patch("copr_backend.sign.ObsSign._sign_one")
++ @mock.patch("copr_backend.sign.ObsSign.create_user_keys")
++ @mock.patch("copr_backend.sign.ObsSign.get_pubkey")
+ def test_sign_rpms_id_dir_sign_error_all(
+ self, mc_gp, mc_cuk, mc_so, tmp_dir, tmp_files):
+
+ mc_so.side_effect = CoprSignError("foobar")
+ with pytest.raises(CoprSignError):
+- sign_rpms_in_dir(self.username, self.projectname,
++ self.signer.sign_rpms_in_dir(self.username, self.projectname,
+ self.tmp_dir_path, "fedora-36-i386", self.opts,
+ log=MagicMock())
+