From ffe6aec190b22a441b595c955a3e038d99fc1d66 Mon Sep 17 00:00:00 2001 From: Evgeniy Alekseev Date: Sun, 4 Apr 2021 15:42:06 +0300 Subject: [PATCH] more options in setup command --- package/etc/ahriman.ini | 1 + src/ahriman/application/ahriman.py | 8 ++++- src/ahriman/application/handlers/setup.py | 25 ++++++++++++---- src/ahriman/core/report/html.py | 4 +-- src/ahriman/core/sign/gpg.py | 6 ++-- src/ahriman/models/sign_settings.py | 12 ++++---- .../handlers/test_handler_setup.py | 14 +++++++-- tests/ahriman/application/test_ahriman.py | 3 +- tests/ahriman/core/sign/test_gpg.py | 30 +++++++++---------- tests/ahriman/models/test_sign_settings.py | 14 ++++----- tests/ahriman/web/test_web.py | 4 +-- tests/testresources/core/ahriman.ini | 1 + 12 files changed, 75 insertions(+), 47 deletions(-) diff --git a/package/etc/ahriman.ini b/package/etc/ahriman.ini index 042b9edf..7d1b3582 100644 --- a/package/etc/ahriman.ini +++ b/package/etc/ahriman.ini @@ -41,4 +41,5 @@ command = rsync --archive --verbose --compress --partial --delete command = aws s3 sync --quiet --delete [web] +host = 0.0.0.0 templates = /usr/share/ahriman \ No newline at end of file diff --git a/src/ahriman/application/ahriman.py b/src/ahriman/application/ahriman.py index 8ec79d5f..e72373e5 100644 --- a/src/ahriman/application/ahriman.py +++ b/src/ahriman/application/ahriman.py @@ -28,6 +28,8 @@ from ahriman.models.build_status import BuildStatusEnum # pylint thinks it is bad idea, but get the fuck off # pylint: disable=protected-access +from ahriman.models.sign_settings import SignSettings + SubParserAction = argparse._SubParsersAction @@ -181,7 +183,11 @@ def _set_setup_parser(root: SubParserAction) -> argparse.ArgumentParser: default="/usr/share/devtools/pacman-extra.conf") parser.add_argument("--no-multilib", help="do not add multilib repository", action="store_true") parser.add_argument("--packager", help="packager name and email", required=True) - parser.add_argument("--repository", help="repository name", default="aur-clone") + parser.add_argument("--repository", help="repository name", required=True) + parser.add_argument("--sign-key", help="sign key id") + parser.add_argument("--sign-target", help="sign options", + choices=[sign.name.lower() for sign in SignSettings], nargs="*") + parser.add_argument("--web-port", help="port of the web service", type=int) parser.set_defaults(handler=handlers.Setup, lock=None, no_report=True, unsafe=True) return parser diff --git a/src/ahriman/application/handlers/setup.py b/src/ahriman/application/handlers/setup.py index 3c2af4d8..de58858c 100644 --- a/src/ahriman/application/handlers/setup.py +++ b/src/ahriman/application/handlers/setup.py @@ -56,7 +56,7 @@ class Setup(Handler): Setup.create_executable(args.build_command, architecture) Setup.create_devtools_configuration(args.build_command, architecture, Path(args.from_configuration), args.no_multilib, args.repository, application.repository.paths) - Setup.create_ahriman_configuration(args.build_command, architecture, args.repository, configuration.include) + Setup.create_ahriman_configuration(args, architecture, args.repository, configuration.include) Setup.create_sudo_configuration(args.build_command, architecture) @staticmethod @@ -70,23 +70,36 @@ class Setup(Handler): return Setup.BIN_DIR_PATH / f"{prefix}-{architecture}-build" @staticmethod - def create_ahriman_configuration(prefix: str, architecture: str, repository: str, include_path: Path) -> None: + def create_ahriman_configuration(args: argparse.Namespace, architecture: str, repository: str, + include_path: Path) -> None: """ create service specific configuration - :param prefix: command prefix in {prefix}-{architecture}-build + :param args: command line args :param architecture: repository architecture :param repository: repository name :param include_path: path to directory with configuration includes """ configuration = configparser.ConfigParser() - configuration.add_section("build") - configuration.set("build", "build_command", str(Setup.build_command(prefix, architecture))) + section = Configuration.section_name("build", architecture) + configuration.add_section(section) + configuration.set(section, "build_command", str(Setup.build_command(args.build_command, architecture))) configuration.add_section("repository") configuration.set("repository", "name", repository) - target = include_path / "build-overrides.ini" + if args.sign_key is not None: + section = Configuration.section_name("sign", architecture) + configuration.add_section(section) + configuration.set(section, "target", " ".join(args.sign_target)) + configuration.set(section, "key", args.sign_key) + + if args.web_port is not None: + section = Configuration.section_name("web", architecture) + configuration.add_section(section) + configuration.set(section, "port", str(args.web_port)) + + target = include_path / "setup-overrides.ini" with target.open("w") as ahriman_configuration: configuration.write(ahriman_configuration) diff --git a/src/ahriman/core/report/html.py b/src/ahriman/core/report/html.py index 10b5e718..4d9da26b 100644 --- a/src/ahriman/core/report/html.py +++ b/src/ahriman/core/report/html.py @@ -112,8 +112,8 @@ class HTML(Report): html = template.render( homepage=self.homepage, link_path=self.link_path, - has_package_signed=SignSettings.SignPackages in self.sign_targets, - has_repo_signed=SignSettings.SignRepository in self.sign_targets, + has_package_signed=SignSettings.Packages in self.sign_targets, + has_repo_signed=SignSettings.Repository in self.sign_targets, packages=sorted(content, key=comparator), pgp_key=self.default_pgp_key, repository=self.name) diff --git a/src/ahriman/core/sign/gpg.py b/src/ahriman/core/sign/gpg.py index ff835938..04795b65 100644 --- a/src/ahriman/core/sign/gpg.py +++ b/src/ahriman/core/sign/gpg.py @@ -56,7 +56,7 @@ class GPG: """ :return: command line arguments for repo-add command to sign database """ - if SignSettings.SignRepository not in self.targets: + if SignSettings.Repository not in self.targets: return [] if self.default_key is None: self.logger.error("no default key set, skip repository sign") @@ -107,7 +107,7 @@ class GPG: :param base: package base required to check for key overrides :return: list of generated files including original file """ - if SignSettings.SignPackages not in self.targets: + if SignSettings.Packages not in self.targets: return [path] key = self.configuration.get("sign", f"key_{base}", fallback=self.default_key) if key is None: @@ -122,7 +122,7 @@ class GPG: :param path: path to repository database :return: list of generated files including original file """ - if SignSettings.SignRepository not in self.targets: + if SignSettings.Repository not in self.targets: return [path] if self.default_key is None: self.logger.error("no default key set, skip repository sign") diff --git a/src/ahriman/models/sign_settings.py b/src/ahriman/models/sign_settings.py index 918c38a2..0744ceea 100644 --- a/src/ahriman/models/sign_settings.py +++ b/src/ahriman/models/sign_settings.py @@ -28,12 +28,12 @@ from ahriman.core.exceptions import InvalidOption class SignSettings(Enum): """ sign targets enumeration - :cvar SignPackages: sign each package - :cvar SignRepository: sign repository database file + :cvar Packages: sign each package + :cvar Repository: sign repository database file """ - SignPackages = auto() - SignRepository = auto() + Packages = auto() + Repository = auto() @classmethod def from_option(cls: Type[SignSettings], value: str) -> SignSettings: @@ -43,7 +43,7 @@ class SignSettings(Enum): :return: parsed value """ if value.lower() in ("package", "packages", "sign-package"): - return cls.SignPackages + return cls.Packages if value.lower() in ("repository", "sign-repository"): - return cls.SignRepository + return cls.Repository raise InvalidOption(value) diff --git a/tests/ahriman/application/handlers/test_handler_setup.py b/tests/ahriman/application/handlers/test_handler_setup.py index 6f83e4ad..399ca79a 100644 --- a/tests/ahriman/application/handlers/test_handler_setup.py +++ b/tests/ahriman/application/handlers/test_handler_setup.py @@ -15,6 +15,9 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace: args.no_multilib = False args.packager = "John Doe " args.repository = "aur-clone" + args.sign_key = "key" + args.sign_target = ["packages"] + args.web_port = 8080 return args @@ -58,14 +61,19 @@ def test_create_ahriman_configuration(args: argparse.Namespace, configuration: C write_mock = mocker.patch("configparser.RawConfigParser.write") command = Setup.build_command(args.build_command, "x86_64") - Setup.create_ahriman_configuration(args.build_command, "x86_64", args.repository, configuration.include) + Setup.create_ahriman_configuration(args, "x86_64", args.repository, configuration.include) add_section_mock.assert_has_calls([ - mock.call("build"), + mock.call(Configuration.section_name("build", "x86_64")), mock.call("repository"), + mock.call(Configuration.section_name("sign", "x86_64")), + mock.call(Configuration.section_name("web", "x86_64")), ]) set_mock.assert_has_calls([ - mock.call("build", "build_command", str(command)), + mock.call(Configuration.section_name("build", "x86_64"), "build_command", str(command)), mock.call("repository", "name", args.repository), + mock.call(Configuration.section_name("sign", "x86_64"), "target", " ".join(args.sign_target)), + mock.call(Configuration.section_name("sign", "x86_64"), "key", args.sign_key), + mock.call(Configuration.section_name("web", "x86_64"), "port", str(args.web_port)), ]) write_mock.assert_called_once() diff --git a/tests/ahriman/application/test_ahriman.py b/tests/ahriman/application/test_ahriman.py index 435a7ff9..fb13909a 100644 --- a/tests/ahriman/application/test_ahriman.py +++ b/tests/ahriman/application/test_ahriman.py @@ -52,7 +52,8 @@ def test_subparsers_setup(parser: argparse.ArgumentParser) -> None: """ setup command must imply lock, no_report and unsafe """ - args = parser.parse_args(["-a", "x86_64", "setup", "--packager", "John Doe "]) + args = parser.parse_args(["-a", "x86_64", "setup", "--packager", "John Doe ", + "--repository", "aur-clone"]) assert args.lock is None assert args.no_report assert args.unsafe diff --git a/tests/ahriman/core/sign/test_gpg.py b/tests/ahriman/core/sign/test_gpg.py index b5659747..6fa70f9d 100644 --- a/tests/ahriman/core/sign/test_gpg.py +++ b/tests/ahriman/core/sign/test_gpg.py @@ -9,7 +9,7 @@ def test_repository_sign_args_1(gpg_with_key: GPG) -> None: """ must generate correct sign args """ - gpg_with_key.targets = {SignSettings.SignRepository} + gpg_with_key.targets = {SignSettings.Repository} assert gpg_with_key.repository_sign_args @@ -17,7 +17,7 @@ def test_repository_sign_args_2(gpg_with_key: GPG) -> None: """ must generate correct sign args """ - gpg_with_key.targets = {SignSettings.SignPackages, SignSettings.SignRepository} + gpg_with_key.targets = {SignSettings.Packages, SignSettings.Repository} assert gpg_with_key.repository_sign_args @@ -33,7 +33,7 @@ def test_repository_sign_args_skip_2(gpg_with_key: GPG) -> None: """ must return empty args if it is not set """ - gpg_with_key.targets = {SignSettings.SignPackages} + gpg_with_key.targets = {SignSettings.Packages} assert not gpg_with_key.repository_sign_args @@ -41,7 +41,7 @@ def test_repository_sign_args_skip_3(gpg: GPG) -> None: """ must return empty args if it is not set """ - gpg.targets = {SignSettings.SignRepository} + gpg.targets = {SignSettings.Repository} assert not gpg.repository_sign_args @@ -49,7 +49,7 @@ def test_repository_sign_args_skip_4(gpg: GPG) -> None: """ must return empty args if it is not set """ - gpg.targets = {SignSettings.SignPackages, SignSettings.SignRepository} + gpg.targets = {SignSettings.Packages, SignSettings.Repository} assert not gpg.repository_sign_args @@ -78,7 +78,7 @@ def test_sign_package_1(gpg_with_key: GPG, mocker: MockerFixture) -> None: result = [Path("a"), Path("a.sig")] process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process", return_value=result) - gpg_with_key.targets = {SignSettings.SignPackages} + gpg_with_key.targets = {SignSettings.Packages} assert gpg_with_key.sign_package(Path("a"), "a") == result process_mock.assert_called_once() @@ -90,7 +90,7 @@ def test_sign_package_2(gpg_with_key: GPG, mocker: MockerFixture) -> None: result = [Path("a"), Path("a.sig")] process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process", return_value=result) - gpg_with_key.targets = {SignSettings.SignPackages, SignSettings.SignRepository} + gpg_with_key.targets = {SignSettings.Packages, SignSettings.Repository} assert gpg_with_key.sign_package(Path("a"), "a") == result process_mock.assert_called_once() @@ -110,7 +110,7 @@ def test_sign_package_skip_2(gpg_with_key: GPG, mocker: MockerFixture) -> None: must not sign package if it is not set """ process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process") - gpg_with_key.targets = {SignSettings.SignRepository} + gpg_with_key.targets = {SignSettings.Repository} gpg_with_key.sign_package(Path("a"), "a") process_mock.assert_not_called() @@ -120,7 +120,7 @@ def test_sign_package_skip_3(gpg: GPG, mocker: MockerFixture) -> None: must not sign package if it is not set """ process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process") - gpg.targets = {SignSettings.SignPackages} + gpg.targets = {SignSettings.Packages} gpg.sign_package(Path("a"), "a") process_mock.assert_not_called() @@ -130,7 +130,7 @@ def test_sign_package_skip_4(gpg: GPG, mocker: MockerFixture) -> None: must not sign package if it is not set """ process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process") - gpg.targets = {SignSettings.SignPackages, SignSettings.SignRepository} + gpg.targets = {SignSettings.Packages, SignSettings.Repository} gpg.sign_package(Path("a"), "a") process_mock.assert_not_called() @@ -142,7 +142,7 @@ def test_sign_repository_1(gpg_with_key: GPG, mocker: MockerFixture) -> None: result = [Path("a"), Path("a.sig")] process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process", return_value=result) - gpg_with_key.targets = {SignSettings.SignRepository} + gpg_with_key.targets = {SignSettings.Repository} assert gpg_with_key.sign_repository(Path("a")) == result process_mock.assert_called_once() @@ -154,7 +154,7 @@ def test_sign_repository_2(gpg_with_key: GPG, mocker: MockerFixture) -> None: result = [Path("a"), Path("a.sig")] process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process", return_value=result) - gpg_with_key.targets = {SignSettings.SignPackages, SignSettings.SignRepository} + gpg_with_key.targets = {SignSettings.Packages, SignSettings.Repository} assert gpg_with_key.sign_repository(Path("a")) == result process_mock.assert_called_once() @@ -174,7 +174,7 @@ def test_sign_repository_skip_2(gpg_with_key: GPG, mocker: MockerFixture) -> Non must not sign repository if it is not set """ process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process") - gpg_with_key.targets = {SignSettings.SignPackages} + gpg_with_key.targets = {SignSettings.Packages} gpg_with_key.sign_repository(Path("a")) process_mock.assert_not_called() @@ -184,7 +184,7 @@ def test_sign_repository_skip_3(gpg: GPG, mocker: MockerFixture) -> None: must not sign repository if it is not set """ process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process") - gpg.targets = {SignSettings.SignRepository} + gpg.targets = {SignSettings.Repository} gpg.sign_repository(Path("a")) process_mock.assert_not_called() @@ -194,6 +194,6 @@ def test_sign_repository_skip_4(gpg: GPG, mocker: MockerFixture) -> None: must not sign repository if it is not set """ process_mock = mocker.patch("ahriman.core.sign.gpg.GPG.process") - gpg.targets = {SignSettings.SignPackages, SignSettings.SignRepository} + gpg.targets = {SignSettings.Packages, SignSettings.Repository} gpg.sign_repository(Path("a")) process_mock.assert_not_called() diff --git a/tests/ahriman/models/test_sign_settings.py b/tests/ahriman/models/test_sign_settings.py index 5555e5fd..e282c93b 100644 --- a/tests/ahriman/models/test_sign_settings.py +++ b/tests/ahriman/models/test_sign_settings.py @@ -16,11 +16,11 @@ def test_from_option_valid() -> None: """ must return value from valid options """ - assert SignSettings.from_option("package") == SignSettings.SignPackages - assert SignSettings.from_option("PACKAGE") == SignSettings.SignPackages - assert SignSettings.from_option("packages") == SignSettings.SignPackages - assert SignSettings.from_option("sign-package") == SignSettings.SignPackages + assert SignSettings.from_option("package") == SignSettings.Packages + assert SignSettings.from_option("PACKAGE") == SignSettings.Packages + assert SignSettings.from_option("packages") == SignSettings.Packages + assert SignSettings.from_option("sign-package") == SignSettings.Packages - assert SignSettings.from_option("repository") == SignSettings.SignRepository - assert SignSettings.from_option("REPOSITORY") == SignSettings.SignRepository - assert SignSettings.from_option("sign-repository") == SignSettings.SignRepository + assert SignSettings.from_option("repository") == SignSettings.Repository + assert SignSettings.from_option("REPOSITORY") == SignSettings.Repository + assert SignSettings.from_option("sign-repository") == SignSettings.Repository diff --git a/tests/ahriman/web/test_web.py b/tests/ahriman/web/test_web.py index 3ad07c00..f0c42c23 100644 --- a/tests/ahriman/web/test_web.py +++ b/tests/ahriman/web/test_web.py @@ -34,12 +34,10 @@ def test_run(application: web.Application, mocker: MockerFixture) -> None: """ must run application """ - host = "localhost" port = 8080 - application["configuration"].set("web", "host", host) application["configuration"].set("web", "port", str(port)) run_application_mock = mocker.patch("aiohttp.web.run_app") run_server(application) - run_application_mock.assert_called_with(application, host=host, port=port, + run_application_mock.assert_called_with(application, host="0.0.0.0", port=port, handle_signals=False, access_log=pytest.helpers.anyvar(int)) diff --git a/tests/testresources/core/ahriman.ini b/tests/testresources/core/ahriman.ini index c8efca23..b5432f05 100644 --- a/tests/testresources/core/ahriman.ini +++ b/tests/testresources/core/ahriman.ini @@ -43,4 +43,5 @@ bucket = command = aws s3 sync --quiet --delete [web] +host = 0.0.0.0 templates = ../web/templates \ No newline at end of file