apply results of "cmdeploy fmt"

This commit is contained in:
holger krekel
2025-11-13 17:48:13 +01:00
parent ae96b752a3
commit 3c3e54fceb
10 changed files with 46 additions and 29 deletions

View File

@@ -27,7 +27,9 @@ class AcmetoolDeployer(Deployer):
files.put( files.put(
name="Install acmetool hook.", name="Install acmetool hook.",
src=importlib.resources.files(__package__).joinpath("acmetool.hook").open("rb"), src=importlib.resources.files(__package__)
.joinpath("acmetool.hook")
.open("rb"),
dest="/etc/acme/hooks/nginx", dest="/etc/acme/hooks/nginx",
user="root", user="root",
group="root", group="root",
@@ -41,7 +43,9 @@ class AcmetoolDeployer(Deployer):
def configure(self): def configure(self):
files.template( files.template(
src=importlib.resources.files(__package__).joinpath("response-file.yaml.j2"), src=importlib.resources.files(__package__).joinpath(
"response-file.yaml.j2"
),
dest="/var/lib/acme/conf/responses", dest="/var/lib/acme/conf/responses",
user="root", user="root",
group="root", group="root",
@@ -80,7 +84,9 @@ class AcmetoolDeployer(Deployer):
self.need_restart_reconcile_service = reconcile_service_file.changed self.need_restart_reconcile_service = reconcile_service_file.changed
reconcile_timer_file = files.put( reconcile_timer_file = files.put(
src=importlib.resources.files(__package__).joinpath("acmetool-reconcile.timer"), src=importlib.resources.files(__package__).joinpath(
"acmetool-reconcile.timer"
),
dest="/etc/systemd/system/acmetool-reconcile.timer", dest="/etc/systemd/system/acmetool-reconcile.timer",
user="root", user="root",
group="root", group="root",

View File

@@ -19,7 +19,7 @@ from packaging import version
from termcolor import colored from termcolor import colored
from . import dns, remote from . import dns, remote
from .sshexec import SSHExec, LocalExec from .sshexec import LocalExec, SSHExec
# #
# cmdeploy sub commands and options # cmdeploy sub commands and options
@@ -309,7 +309,7 @@ def add_ssh_host_option(parser):
"--ssh-host", "--ssh-host",
dest="ssh_host", dest="ssh_host",
help="Run commands on 'localhost', via '@docker', or on a specific SSH host " help="Run commands on 'localhost', via '@docker', or on a specific SSH host "
"instead of chatmail.ini's mail_domain.", "instead of chatmail.ini's mail_domain.",
) )

View File

@@ -11,7 +11,6 @@ from io import StringIO
from pathlib import Path from pathlib import Path
from chatmaild.config import Config, read_config from chatmaild.config import Config, read_config
from cmdeploy.cmdeploy import Out
from pyinfra import facts, host, logger from pyinfra import facts, host, logger
from pyinfra.api import FactBase from pyinfra.api import FactBase
from pyinfra.facts.files import File, Sha256File from pyinfra.facts.files import File, Sha256File
@@ -19,6 +18,8 @@ from pyinfra.facts.server import Sysctl
from pyinfra.facts.systemd import SystemdEnabled from pyinfra.facts.systemd import SystemdEnabled
from pyinfra.operations import apt, files, pip, server, systemd from pyinfra.operations import apt, files, pip, server, systemd
from cmdeploy.cmdeploy import Out
from .acmetool import AcmetoolDeployer from .acmetool import AcmetoolDeployer
from .basedeploy import Deployer, Deployment from .basedeploy import Deployer, Deployment
from .www import build_webpages, find_merge_conflict, get_paths from .www import build_webpages, find_merge_conflict, get_paths
@@ -148,7 +149,9 @@ def _configure_remote_units(mail_domain, units) -> None:
basename = fn if "." in fn else f"{fn}.service" basename = fn if "." in fn else f"{fn}.service"
source_path = importlib.resources.files(__package__).joinpath("service", f"{basename}.f") source_path = importlib.resources.files(__package__).joinpath(
"service", f"{basename}.f"
)
content = source_path.read_text().format(**params).encode() content = source_path.read_text().format(**params).encode()
files.put( files.put(
@@ -179,7 +182,6 @@ def _activate_remote_units(units) -> None:
) )
def _configure_opendkim(domain: str, dkim_selector: str = "dkim") -> bool: def _configure_opendkim(domain: str, dkim_selector: str = "dkim") -> bool:
"""Configures OpenDKIM""" """Configures OpenDKIM"""
need_restart = False need_restart = False
@@ -437,7 +439,9 @@ class PostfixDeployer(Deployer):
restart = False if self.disable_mail else self.need_restart restart = False if self.disable_mail else self.need_restart
systemd.service( systemd.service(
name="disable postfix for now" if self.disable_mail else "Start and enable Postfix", name="disable postfix for now"
if self.disable_mail
else "Start and enable Postfix",
service="postfix.service", service="postfix.service",
running=False if self.disable_mail else True, running=False if self.disable_mail else True,
enabled=False if self.disable_mail else True, enabled=False if self.disable_mail else True,
@@ -569,7 +573,9 @@ class DovecotDeployer(Deployer):
restart = False if self.disable_mail else self.need_restart restart = False if self.disable_mail else self.need_restart
systemd.service( systemd.service(
name="disable dovecot for now" if self.disable_mail else "Start and enable Dovecot", name="disable dovecot for now"
if self.disable_mail
else "Start and enable Dovecot",
service="dovecot.service", service="dovecot.service",
running=False if self.disable_mail else True, running=False if self.disable_mail else True,
enabled=False if self.disable_mail else True, enabled=False if self.disable_mail else True,
@@ -708,7 +714,9 @@ class WebsiteDeployer(Deployer):
if not www_path.is_dir(): if not www_path.is_dir():
logger.warning("Building web pages is disabled in chatmail.ini, skipping") logger.warning("Building web pages is disabled in chatmail.ini, skipping")
elif (path := find_merge_conflict(src_dir)) is not None: elif (path := find_merge_conflict(src_dir)) is not None:
logger.warning(f"Merge conflict found in {path}, skipping website deployment. Fix merge conflict if you want to upload your web page.") logger.warning(
f"Merge conflict found in {path}, skipping website deployment. Fix merge conflict if you want to upload your web page."
)
else: else:
# if www_folder is a hugo page, build it # if www_folder is a hugo page, build it
if build_dir: if build_dir:
@@ -1106,12 +1114,10 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None:
TurnDeployer(mail_domain), TurnDeployer(mail_domain),
IrohDeployer(config.enable_iroh_relay), IrohDeployer(config.enable_iroh_relay),
AcmetoolDeployer(config.acme_email, tls_domains), AcmetoolDeployer(config.acme_email, tls_domains),
WebsiteDeployer(config), WebsiteDeployer(config),
ChatmailVenvDeployer(config), ChatmailVenvDeployer(config),
MtastsDeployer(), MtastsDeployer(),
OpendkimDeployer(mail_domain), OpendkimDeployer(mail_domain),
# Dovecot should be started before Postfix # Dovecot should be started before Postfix
# because it creates authentication socket # because it creates authentication socket
# required by Postfix. # required by Postfix.

View File

@@ -45,7 +45,8 @@ def check_full_zone(sshexec, remote_data, out, zonefile) -> int:
and return (exitcode, remote_data) tuple.""" and return (exitcode, remote_data) tuple."""
required_diff, recommended_diff = sshexec.logged( required_diff, recommended_diff = sshexec.logged(
remote.rdns.check_zonefile, kwargs=dict(zonefile=zonefile, verbose=False), remote.rdns.check_zonefile,
kwargs=dict(zonefile=zonefile, verbose=False),
) )
returncode = 0 returncode = 0

View File

@@ -12,7 +12,7 @@ All functions of this module
import re import re
from .rshell import CalledProcessError, shell, log_progress from .rshell import CalledProcessError, log_progress, shell
def perform_initial_checks(mail_domain, pre_command=""): def perform_initial_checks(mail_domain, pre_command=""):
@@ -26,7 +26,9 @@ def perform_initial_checks(mail_domain, pre_command=""):
WWW = query_dns("CNAME", f"www.{mail_domain}") WWW = query_dns("CNAME", f"www.{mail_domain}")
res = dict(mail_domain=mail_domain, A=A, AAAA=AAAA, MTA_STS=MTA_STS, WWW=WWW) res = dict(mail_domain=mail_domain, A=A, AAAA=AAAA, MTA_STS=MTA_STS, WWW=WWW)
res["acme_account_url"] = shell(pre_command + "acmetool account-url", fail_ok=True, print=log_progress) res["acme_account_url"] = shell(
pre_command + "acmetool account-url", fail_ok=True, print=log_progress
)
res["dkim_entry"], res["web_dkim_entry"] = get_dkim_entry( res["dkim_entry"], res["web_dkim_entry"] = get_dkim_entry(
mail_domain, pre_command, dkim_selector="opendkim" mail_domain, pre_command, dkim_selector="opendkim"
) )
@@ -45,7 +47,7 @@ def get_dkim_entry(mail_domain, pre_command, dkim_selector):
dkim_pubkey = shell( dkim_pubkey = shell(
f"{pre_command}openssl rsa -in /etc/dkimkeys/{dkim_selector}.private " f"{pre_command}openssl rsa -in /etc/dkimkeys/{dkim_selector}.private "
"-pubout 2>/dev/null | awk '/-/{next}{printf(\"%s\",$0)}'", "-pubout 2>/dev/null | awk '/-/{next}{printf(\"%s\",$0)}'",
print=log_progress print=log_progress,
) )
except CalledProcessError: except CalledProcessError:
return return
@@ -62,9 +64,9 @@ def query_dns(typ, domain):
# Get autoritative nameserver from the SOA record. # Get autoritative nameserver from the SOA record.
soa_answers = [ soa_answers = [
x.split() x.split()
for x in shell(f"dig -r -q {domain} -t SOA +noall +authority +answer", print=log_progress).split( for x in shell(
"\n" f"dig -r -q {domain} -t SOA +noall +authority +answer", print=log_progress
) ).split("\n")
] ]
soa = [a for a in soa_answers if len(a) >= 3 and a[3] == "SOA"] soa = [a for a in soa_answers if len(a) >= 3 and a[3] == "SOA"]
if not soa: if not soa:
@@ -73,7 +75,7 @@ def query_dns(typ, domain):
# Query authoritative nameserver directly to bypass DNS cache. # Query authoritative nameserver directly to bypass DNS cache.
res = shell(f"dig @{ns} -r -q {domain} -t {typ} +short", print=log_progress) res = shell(f"dig @{ns} -r -q {domain} -t {typ} +short", print=log_progress)
return next((line for line in res.split("\n") if not line.startswith(';')), '') return next((line for line in res.split("\n") if not line.startswith(";")), "")
def check_zonefile(zonefile, verbose=True): def check_zonefile(zonefile, verbose=True):

View File

@@ -1,5 +1,4 @@
import sys import sys
from subprocess import DEVNULL, CalledProcessError, check_output from subprocess import DEVNULL, CalledProcessError, check_output

View File

@@ -93,7 +93,7 @@ class LocalExec:
where = "locally" where = "locally"
if self.docker: if self.docker:
if call == remote.rdns.perform_initial_checks: if call == remote.rdns.perform_initial_checks:
kwargs['pre_command'] = "docker exec chatmail " kwargs["pre_command"] = "docker exec chatmail "
where = "in docker" where = "in docker"
if self.verbose: if self.verbose:
print(f"Running {where}: {call.__name__}(**{kwargs})") print(f"Running {where}: {call.__name__}(**{kwargs})")

View File

@@ -35,7 +35,7 @@ class TestSSHExecutor:
out, err = capsys.readouterr() out, err = capsys.readouterr()
assert err.startswith("Collecting") assert err.startswith("Collecting")
# XXX could not figure out how capturing can be made to work properly # XXX could not figure out how capturing can be made to work properly
#assert err.endswith("....\n") # assert err.endswith("....\n")
assert err.count("\n") == 1 assert err.count("\n") == 1
sshexec.verbose = True sshexec.verbose = True
@@ -45,7 +45,7 @@ class TestSSHExecutor:
out, err = capsys.readouterr() out, err = capsys.readouterr()
lines = err.split("\n") lines = err.split("\n")
# XXX could not figure out how capturing can be made to work properly # XXX could not figure out how capturing can be made to work properly
#assert len(lines) > 4 # assert len(lines) > 4
assert remote.rdns.perform_initial_checks.__doc__ in lines[0] assert remote.rdns.perform_initial_checks.__doc__ in lines[0]
def test_exception(self, sshexec, capsys): def test_exception(self, sshexec, capsys):

View File

@@ -65,7 +65,9 @@ class TestPerformInitialChecks:
remote_data = remote.rdns.perform_initial_checks("some.domain") remote_data = remote.rdns.perform_initial_checks("some.domain")
assert remote_data["A"] == mockdns_expected["A"]["some.domain"] assert remote_data["A"] == mockdns_expected["A"]["some.domain"]
assert remote_data["AAAA"] == mockdns_expected["AAAA"]["some.domain"] assert remote_data["AAAA"] == mockdns_expected["AAAA"]["some.domain"]
assert remote_data["MTA_STS"] == mockdns_expected["CNAME"]["mta-sts.some.domain"] assert (
remote_data["MTA_STS"] == mockdns_expected["CNAME"]["mta-sts.some.domain"]
)
assert remote_data["WWW"] == mockdns_expected["CNAME"]["www.some.domain"] assert remote_data["WWW"] == mockdns_expected["CNAME"]["www.some.domain"]
@pytest.mark.parametrize("drop", ["A", "AAAA"]) @pytest.mark.parametrize("drop", ["A", "AAAA"])

View File

@@ -1,10 +1,10 @@
import hashlib import hashlib
import importlib.resources import importlib.resources
import re
import time import time
import traceback import traceback
import webbrowser import webbrowser
from pathlib import Path from pathlib import Path
import re
import markdown import markdown
from chatmaild.config import read_config from chatmaild.config import read_config
@@ -12,8 +12,9 @@ from jinja2 import Template
from .genqr import gen_qr_png_data from .genqr import gen_qr_png_data
_MERGE_CONFLICT_RE = re.compile(
_MERGE_CONFLICT_RE = re.compile(r"^<<<<<<<.+^=======.+^>>>>>>>", re.DOTALL | re.MULTILINE) r"^<<<<<<<.+^=======.+^>>>>>>>", re.DOTALL | re.MULTILINE
)
def snapshot_dir_stats(somedir): def snapshot_dir_stats(somedir):