allow to use multiple upload and report targets with the same name

In this feature target option must allways point to section name instead
of type. Type will be read from type option. In case if type option is
not presented it will try to check if section with architecture exists
(e.g. target = email, section = email:x86_64); if it does, the correct
section name and type will be used. Otherwise it will check if the
specified section exists; if it does, seection name and type will be
returned.
This commit is contained in:
2021-10-17 05:33:23 +03:00
parent fd38dfd176
commit 20962f0385
17 changed files with 274 additions and 131 deletions

View File

@ -11,7 +11,7 @@ def test_send(configuration: Configuration, mocker: MockerFixture) -> None:
"""
smtp_mock = mocker.patch("smtplib.SMTP")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.starttls.assert_not_called()
smtp_mock.return_value.login.assert_not_called()
@ -27,7 +27,7 @@ def test_send_auth(configuration: Configuration, mocker: MockerFixture) -> None:
configuration.set_option("email", "password", "password")
smtp_mock = mocker.patch("smtplib.SMTP")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.login.assert_called_once()
@ -39,7 +39,7 @@ def test_send_auth_no_password(configuration: Configuration, mocker: MockerFixtu
configuration.set_option("email", "user", "username")
smtp_mock = mocker.patch("smtplib.SMTP")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.login.assert_not_called()
@ -51,7 +51,7 @@ def test_send_auth_no_user(configuration: Configuration, mocker: MockerFixture)
configuration.set_option("email", "password", "password")
smtp_mock = mocker.patch("smtplib.SMTP")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.login.assert_not_called()
@ -63,7 +63,7 @@ def test_send_ssl_tls(configuration: Configuration, mocker: MockerFixture) -> No
configuration.set_option("email", "ssl", "ssl")
smtp_mock = mocker.patch("smtplib.SMTP_SSL")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.starttls.assert_not_called()
smtp_mock.return_value.login.assert_not_called()
@ -78,7 +78,7 @@ def test_send_starttls(configuration: Configuration, mocker: MockerFixture) -> N
configuration.set_option("email", "ssl", "starttls")
smtp_mock = mocker.patch("smtplib.SMTP")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report._send("a text", {"attachment.html": "an attachment"})
smtp_mock.return_value.starttls.assert_called_once()
@ -89,7 +89,7 @@ def test_generate(configuration: Configuration, package_ahriman: Package, mocker
"""
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report.generate([package_ahriman], [])
send_mock.assert_called_once()
@ -100,7 +100,7 @@ def test_generate_with_built(configuration: Configuration, package_ahriman: Pack
"""
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report.generate([package_ahriman], [package_ahriman])
send_mock.assert_called_once()
@ -114,7 +114,7 @@ def test_generate_with_built_and_full_path(
"""
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report.full_template_path = report.template_path
report.generate([package_ahriman], [package_ahriman])
send_mock.assert_called_once()
@ -127,7 +127,7 @@ def test_generate_no_empty(configuration: Configuration, package_ahriman: Packag
configuration.set_option("email", "no_empty_report", "yes")
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report.generate([package_ahriman], [])
send_mock.assert_not_called()
@ -140,6 +140,6 @@ def test_generate_no_empty_with_built(configuration: Configuration, package_ahri
configuration.set_option("email", "no_empty_report", "yes")
send_mock = mocker.patch("ahriman.core.report.email.Email._send")
report = Email("x86_64", configuration)
report = Email("x86_64", configuration, "email")
report.generate([package_ahriman], [package_ahriman])
send_mock.assert_called_once()

View File

@ -11,6 +11,6 @@ def test_generate(configuration: Configuration, package_ahriman: Package, mocker
"""
write_mock = mocker.patch("pathlib.Path.write_text")
report = HTML("x86_64", configuration)
report = HTML("x86_64", configuration, "html")
report.generate([package_ahriman], [])
write_mock.assert_called_once()

View File

@ -1,6 +1,5 @@
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration
@ -15,7 +14,7 @@ def test_report_failure(configuration: Configuration, mocker: MockerFixture) ->
"""
mocker.patch("ahriman.core.report.html.HTML.generate", side_effect=Exception())
with pytest.raises(ReportFailed):
Report.load("x86_64", configuration, ReportSettings.HTML.name).run(Path("path"), [])
Report.load("x86_64", configuration, "html").run([], [])
def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> None:
@ -24,7 +23,7 @@ def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> No
"""
mocker.patch("ahriman.models.report_settings.ReportSettings.from_option", return_value=ReportSettings.Disabled)
report_mock = mocker.patch("ahriman.core.report.report.Report.generate")
Report.load("x86_64", configuration, ReportSettings.Disabled.name).run(Path("path"), [])
Report.load("x86_64", configuration, "disabled").run([], [])
report_mock.assert_called_once()
@ -33,7 +32,7 @@ def test_report_email(configuration: Configuration, mocker: MockerFixture) -> No
must generate email report
"""
report_mock = mocker.patch("ahriman.core.report.email.Email.generate")
Report.load("x86_64", configuration, ReportSettings.Email.name).run(Path("path"), [])
Report.load("x86_64", configuration, "email").run([], [])
report_mock.assert_called_once()
@ -42,5 +41,5 @@ def test_report_html(configuration: Configuration, mocker: MockerFixture) -> Non
must generate html report
"""
report_mock = mocker.patch("ahriman.core.report.html.HTML.generate")
Report.load("x86_64", configuration, ReportSettings.HTML.name).run(Path("path"), [])
Report.load("x86_64", configuration, "html").run([], [])
report_mock.assert_called_once()

View File

@ -1,7 +1,7 @@
import configparser
from pathlib import Path
import pytest
from pathlib import Path
from pytest_mock import MockerFixture
from ahriman.core.configuration import Configuration
@ -24,53 +24,6 @@ def test_from_path(mocker: MockerFixture) -> None:
load_logging_mock.assert_called_once()
def test_section_name(configuration: Configuration) -> None:
"""
must return architecture specific group
"""
assert configuration.section_name("build", "x86_64") == "build:x86_64"
def test_absolute_path_for_absolute(configuration: Configuration) -> None:
"""
must not change path for absolute path in settings
"""
path = Path("/a/b/c")
configuration.set_option("build", "path", str(path))
assert configuration.getpath("build", "path") == path
def test_absolute_path_for_relative(configuration: Configuration) -> None:
"""
must prepend root path to relative path
"""
path = Path("a")
configuration.set_option("build", "path", str(path))
result = configuration.getpath("build", "path")
assert result.is_absolute()
assert result.parent == configuration.path.parent
assert result.name == path.name
def test_path_with_fallback(configuration: Configuration) -> None:
"""
must return fallback path
"""
path = Path("a")
assert configuration.getpath("some", "option", fallback=path).name == str(path)
assert configuration.getpath("some", "option", fallback=None) is None
def test_path_without_fallback(configuration: Configuration) -> None:
"""
must raise exception without fallback
"""
with pytest.raises(configparser.NoSectionError):
assert configuration.getpath("some", "option")
with pytest.raises(configparser.NoOptionError):
assert configuration.getpath("build", "option")
def test_dump(configuration: Configuration) -> None:
"""
dump must not be empty
@ -93,6 +46,53 @@ def test_dump_architecture_specific(configuration: Configuration) -> None:
assert dump["build"]["archbuild_flags"] == "hello flag"
def test_section_name(configuration: Configuration) -> None:
"""
must return architecture specific group
"""
assert configuration.section_name("build", "x86_64") == "build:x86_64"
def test_getpath_absolute_to_absolute(configuration: Configuration) -> None:
"""
must not change path for absolute path in settings
"""
path = Path("/a/b/c")
configuration.set_option("build", "path", str(path))
assert configuration.getpath("build", "path") == path
def test_getpath_absolute_to_relative(configuration: Configuration) -> None:
"""
must prepend root path to relative path
"""
path = Path("a")
configuration.set_option("build", "path", str(path))
result = configuration.getpath("build", "path")
assert result.is_absolute()
assert result.parent == configuration.path.parent
assert result.name == path.name
def test_getpath_with_fallback(configuration: Configuration) -> None:
"""
must return fallback path
"""
path = Path("a")
assert configuration.getpath("some", "option", fallback=path).name == str(path)
assert configuration.getpath("some", "option", fallback=None) is None
def test_getpath_without_fallback(configuration: Configuration) -> None:
"""
must raise exception without fallback
"""
with pytest.raises(configparser.NoSectionError):
assert configuration.getpath("some", "option")
with pytest.raises(configparser.NoOptionError):
assert configuration.getpath("build", "option")
def test_getlist(configuration: Configuration) -> None:
"""
must return list of string correctly
@ -119,6 +119,43 @@ def test_getlist_single(configuration: Configuration) -> None:
assert configuration.getlist("build", "test_list") == ["a"]
def test_gettype(configuration: Configuration) -> None:
"""
must extract type from variable
"""
section, provider = configuration.gettype("customs3", "x86_64")
assert section == "customs3"
assert provider == "s3"
def test_gettype_from_section(configuration: Configuration) -> None:
"""
must extract type from section name
"""
section, provider = configuration.gettype("rsync", "x86_64")
assert section == "rsync"
assert provider == "rsync"
def test_gettype_from_section_with_architecture(configuration: Configuration) -> None:
"""
must extract type from section name with architecture
"""
section, provider = configuration.gettype("github", "x86_64")
assert section == "github:x86_64"
assert provider == "github"
def test_gettype_from_section_no_section(configuration: Configuration) -> None:
"""
must extract type from section name with architecture
"""
# technically rsync:x86_64 is valid section
# but in current configuration it must be considered as missing section
with pytest.raises(configparser.NoSectionError):
configuration.gettype("rsync:x86_64", "x86_64")
def test_load_includes_missing(configuration: Configuration) -> None:
"""
must not fail if not include directory found
@ -137,7 +174,7 @@ def test_load_includes_no_option(configuration: Configuration) -> None:
def test_load_includes_no_section(configuration: Configuration) -> None:
"""
must not fail if no option set
must not fail if no section set
"""
configuration.remove_section("settings")
configuration.load_includes()

View File

@ -20,7 +20,7 @@ def github(configuration: Configuration) -> Github:
:param configuration: configuration fixture
:return: github test instance
"""
return Github("x86_64", configuration)
return Github("x86_64", configuration, "github:x86_64")
@pytest.fixture
@ -50,7 +50,7 @@ def rsync(configuration: Configuration) -> Rsync:
:param configuration: configuration fixture
:return: rsync test instance
"""
return Rsync("x86_64", configuration)
return Rsync("x86_64", configuration, "rsync")
@pytest.fixture
@ -60,7 +60,7 @@ def s3(configuration: Configuration) -> S3:
:param configuration: configuration fixture
:return: S3 test instance
"""
return S3("x86_64", configuration)
return S3("x86_64", configuration, "customs3")
@pytest.fixture

View File

@ -15,7 +15,7 @@ def test_upload_failure(configuration: Configuration, mocker: MockerFixture) ->
"""
mocker.patch("ahriman.core.upload.rsync.Rsync.sync", side_effect=Exception())
with pytest.raises(SyncFailed):
Upload.load("x86_64", configuration, UploadSettings.Rsync.name).run(Path("path"), [])
Upload.load("x86_64", configuration, "rsync").run(Path("path"), [])
def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> None:
@ -24,7 +24,7 @@ def test_report_dummy(configuration: Configuration, mocker: MockerFixture) -> No
"""
mocker.patch("ahriman.models.upload_settings.UploadSettings.from_option", return_value=UploadSettings.Disabled)
upload_mock = mocker.patch("ahriman.core.upload.upload.Upload.sync")
Upload.load("x86_64", configuration, UploadSettings.Disabled.name).run(Path("path"), [])
Upload.load("x86_64", configuration, "disabled").run(Path("path"), [])
upload_mock.assert_called_once()
@ -33,7 +33,7 @@ def test_upload_rsync(configuration: Configuration, mocker: MockerFixture) -> No
must upload via rsync
"""
upload_mock = mocker.patch("ahriman.core.upload.rsync.Rsync.sync")
Upload.load("x86_64", configuration, UploadSettings.Rsync.name).run(Path("path"), [])
Upload.load("x86_64", configuration, "rsync").run(Path("path"), [])
upload_mock.assert_called_once()
@ -42,7 +42,7 @@ def test_upload_s3(configuration: Configuration, mocker: MockerFixture) -> None:
must upload via s3
"""
upload_mock = mocker.patch("ahriman.core.upload.s3.S3.sync")
Upload.load("x86_64", configuration, UploadSettings.S3.name).run(Path("path"), [])
Upload.load("x86_64", configuration, "customs3").run(Path("path"), [])
upload_mock.assert_called_once()
@ -51,5 +51,5 @@ def test_upload_github(configuration: Configuration, mocker: MockerFixture) -> N
must upload via github
"""
upload_mock = mocker.patch("ahriman.core.upload.github.Github.sync")
Upload.load("x86_64", configuration, UploadSettings.Github.name).run(Path("path"), [])
Upload.load("x86_64", configuration, "github").run(Path("path"), [])
upload_mock.assert_called_once()

View File

@ -55,13 +55,16 @@ target =
command = rsync --archive --verbose --compress --partial --delete
remote =
[s3]
[disabled]
[customs3]
type = s3
access_key =
bucket = bucket
region = eu-central-1
secret_key =
[github]
[github:x86_64]
owner = arcan1s
password =
repository = ahriman