Skip to content

Commit 7831333

Browse files
committed
refactor: use put_file/put_template helpers across all deployers
1 parent 552c12e commit 7831333

9 files changed

Lines changed: 97 additions & 151 deletions

File tree

cmdeploy/src/cmdeploy/basedeploy.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,22 @@ def perform_stages(self, deployers):
9999

100100

101101
class Deployer:
102+
"""Base class for deployers that manage remote service configuration.
103+
104+
Deployers go through three stages: ``install``, ``configure``, and
105+
``activate``. During ``configure``, use :meth:`put_file` and
106+
:meth:`put_template` to upload files — they automatically set
107+
``need_restart = True`` when a file changes on the remote host.
108+
The ``activate`` stage can then inspect ``need_restart`` to decide
109+
whether to restart or reload the managed service.
110+
111+
Deployers with an ``enabled`` flag (default ``True``) support a
112+
disabled mode: when ``enabled`` is ``False``, the ``put_*`` methods
113+
remove the target file from the remote host instead of uploading it,
114+
allowing clean un-deployment of optional components.
115+
"""
116+
117+
enabled = True
102118
need_restart = False
103119
daemon_reload = False
104120

@@ -111,10 +127,15 @@ def configure(self):
111127
def activate(self):
112128
pass
113129

114-
def put_or_remove_file(
130+
def put_file(
115131
self, *, name, dest, src=None, executable=False, owner="root"
116132
):
117-
"""Upload a file or executable, or remove it if deployer is disabled."""
133+
"""Upload a file to *dest*, or remove it when the deployer is disabled.
134+
135+
Sets ``need_restart = True`` when the remote file changes.
136+
When ``self.enabled`` is ``False``, the file at *dest* is removed
137+
instead of uploaded.
138+
"""
118139
if self.enabled:
119140
mode = "755" if executable else "644"
120141
res = files.put(
@@ -127,10 +148,16 @@ def put_or_remove_file(
127148
self.need_restart = True
128149
return res
129150

130-
def put_or_remove_template(
151+
def put_template(
131152
self, *, name, src, dest, owner="root", mode="644", **kwargs
132153
):
133-
"""Upload a templated file or remove it if deployer is disabled."""
154+
"""Upload a Jinja2 template to *dest*, or remove it when disabled.
155+
156+
Sets ``need_restart = True`` when the rendered remote file changes.
157+
When ``self.enabled`` is ``False``, the file at *dest* is removed
158+
instead of uploaded. Extra *kwargs* are passed to the template
159+
as render context.
160+
"""
134161
if self.enabled:
135162
res = files.template(
136163
name=name,

cmdeploy/src/cmdeploy/deployers.py

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -388,25 +388,16 @@ def install(self):
388388
self.need_restart = True
389389

390390
def configure(self):
391-
systemd_unit = files.put(
391+
self.put_file(
392392
name="Upload iroh-relay systemd unit",
393393
src=get_resource("iroh-relay.service"),
394394
dest="/etc/systemd/system/iroh-relay.service",
395-
user="root",
396-
group="root",
397-
mode="644",
398395
)
399-
self.need_restart |= systemd_unit.changed
400-
401-
iroh_config = files.put(
396+
self.put_file(
402397
name="Upload iroh-relay config",
403398
src=get_resource("iroh-relay.toml"),
404399
dest="/etc/iroh-relay.toml",
405-
user="root",
406-
group="root",
407-
mode="644",
408400
)
409-
self.need_restart |= iroh_config.changed
410401

411402
def activate(self):
412403
systemd.service(
@@ -421,15 +412,11 @@ def activate(self):
421412

422413
class JournaldDeployer(Deployer):
423414
def configure(self):
424-
journald_conf = files.put(
415+
self.put_file(
425416
name="Configure journald",
426417
src=get_resource("journald.conf"),
427418
dest="/etc/systemd/journald.conf",
428-
user="root",
429-
group="root",
430-
mode="644",
431419
)
432-
self.need_restart = journald_conf.changed
433420

434421
def activate(self):
435422
systemd.service(

cmdeploy/src/cmdeploy/dovecot/deployer.py

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def install(self):
2929

3030
def configure(self):
3131
configure_remote_units(self.config.mail_domain, self.units)
32-
self.need_restart, self.daemon_reload = _configure_dovecot(self.config)
32+
self.need_restart, self.daemon_reload = _configure_dovecot(self, self.config)
3333

3434
def activate(self):
3535
activate_remote_units(self.units)
@@ -81,38 +81,30 @@ def _install_dovecot_package(package: str, arch: str):
8181
apt.deb(name=f"Install dovecot-{package}", src=deb_filename)
8282

8383

84-
def _configure_dovecot(config: Config, debug: bool = False) -> (bool, bool):
84+
85+
def _configure_dovecot(deployer, config: Config, debug: bool = False) -> (bool, bool):
8586
"""Configures Dovecot IMAP server."""
86-
need_restart = False
87+
deployer.need_restart = False
8788
daemon_reload = False
8889

89-
main_config = files.template(
90+
deployer.put_template(
91+
name="Upload dovecot.conf",
9092
src=get_resource("dovecot/dovecot.conf.j2"),
9193
dest="/etc/dovecot/dovecot.conf",
92-
user="root",
93-
group="root",
94-
mode="644",
9594
config=config,
9695
debug=debug,
9796
disable_ipv6=config.disable_ipv6,
9897
)
99-
need_restart |= main_config.changed
100-
auth_config = files.put(
98+
deployer.put_file(
99+
name="Upload auth.conf",
101100
src=get_resource("dovecot/auth.conf"),
102101
dest="/etc/dovecot/auth.conf",
103-
user="root",
104-
group="root",
105-
mode="644",
106102
)
107-
need_restart |= auth_config.changed
108-
lua_push_notification_script = files.put(
103+
deployer.put_file(
104+
name="Upload push_notification.lua",
109105
src=get_resource("dovecot/push_notification.lua"),
110106
dest="/etc/dovecot/push_notification.lua",
111-
user="root",
112-
group="root",
113-
mode="644",
114107
)
115-
need_restart |= lua_push_notification_script.changed
116108

117109
# as per https://doc.dovecot.org/2.3/configuration_manual/os/
118110
# it is recommended to set the following inotify limits
@@ -134,7 +126,7 @@ def _configure_dovecot(config: Config, debug: bool = False) -> (bool, bool):
134126
path="/etc/environment",
135127
line="TZ=:/etc/localtime",
136128
)
137-
need_restart |= timezone_env.changed
129+
deployer.need_restart |= timezone_env.changed
138130

139131
restart_conf = files.put(
140132
name="dovecot: restart automatically on failure",
@@ -144,10 +136,10 @@ def _configure_dovecot(config: Config, debug: bool = False) -> (bool, bool):
144136
daemon_reload |= restart_conf.changed
145137

146138
# Validate dovecot configuration before restart
147-
if need_restart:
139+
if deployer.need_restart:
148140
server.shell(
149141
name="Validate dovecot configuration",
150142
commands=["doveconf -n >/dev/null"],
151143
)
152144

153-
return need_restart, daemon_reload
145+
return deployer.need_restart, daemon_reload

cmdeploy/src/cmdeploy/filtermail/deployer.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,13 @@ def install(self):
2929

3030
def configure(self):
3131
for service in self.services:
32-
self.need_restart |= files.template(
32+
self.put_template(
33+
name=f"Upload {service}.service",
3334
src=get_resource(f"filtermail/{service}.service.j2"),
3435
dest=f"/etc/systemd/system/{service}.service",
35-
user="root",
36-
group="root",
37-
mode="644",
3836
bin_path=self.bin_path,
3937
config_path=self.config_path,
40-
).changed
38+
)
4139

4240
def activate(self):
4341
for service in self.services:

cmdeploy/src/cmdeploy/mtail/deployer.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from pyinfra import facts, host
2-
from pyinfra.operations import apt, files, server, systemd
2+
from pyinfra.operations import apt, server, systemd
33

44
from cmdeploy.basedeploy import (
55
Deployer,
@@ -37,25 +37,18 @@ def install(self):
3737
def configure(self):
3838
# Using our own systemd unit instead of `/usr/lib/systemd/system/mtail.service`.
3939
# This allows to read from journalctl instead of log files.
40-
files.template(
40+
self.put_template(
41+
name="Upload mtail.service",
4142
src=get_resource("mtail/mtail.service.j2"),
4243
dest="/etc/systemd/system/mtail.service",
43-
user="root",
44-
group="root",
45-
mode="644",
4644
address=self.mtail_address or "127.0.0.1",
4745
port=3903,
4846
)
49-
50-
mtail_conf = files.put(
47+
self.put_file(
5148
name="Mtail configuration",
5249
src=get_resource("mtail/delivered_mail.mtail"),
5350
dest="/etc/mtail/delivered_mail.mtail",
54-
user="root",
55-
group="root",
56-
mode="644",
5751
)
58-
self.need_restart = mtail_conf.changed
5952

6053
def activate(self):
6154
systemd.service(

cmdeploy/src/cmdeploy/nginx/deployer.py

Lines changed: 11 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def install(self):
4747
files.file("/usr/sbin/policy-rc.d", present=False)
4848

4949
def configure(self):
50-
self.need_restart = _configure_nginx(self.config)
50+
_configure_nginx(self, self.config)
5151

5252
def activate(self):
5353
systemd.service(
@@ -60,40 +60,31 @@ def activate(self):
6060
self.need_restart = False
6161

6262

63-
def _configure_nginx(config: Config, debug: bool = False) -> bool:
63+
def _configure_nginx(deployer, config: Config, debug: bool = False):
6464
"""Configures nginx HTTP server."""
65-
need_restart = False
65+
deployer.need_restart = False
6666

67-
main_config = files.template(
67+
deployer.put_template(
68+
name="Upload nginx.conf",
6869
src=get_resource("nginx/nginx.conf.j2"),
6970
dest="/etc/nginx/nginx.conf",
70-
user="root",
71-
group="root",
72-
mode="644",
7371
config=config,
7472
disable_ipv6=config.disable_ipv6,
7573
)
76-
need_restart |= main_config.changed
7774

78-
autoconfig = files.template(
75+
deployer.put_template(
76+
name="Upload autoconfig.xml",
7977
src=get_resource("nginx/autoconfig.xml.j2"),
8078
dest="/var/www/html/.well-known/autoconfig/mail/config-v1.1.xml",
81-
user="root",
82-
group="root",
83-
mode="644",
8479
config=config,
8580
)
86-
need_restart |= autoconfig.changed
8781

88-
mta_sts_config = files.template(
82+
deployer.put_template(
83+
name="Upload mta-sts.txt",
8984
src=get_resource("nginx/mta-sts.txt.j2"),
9085
dest="/var/www/html/.well-known/mta-sts.txt",
91-
user="root",
92-
group="root",
93-
mode="644",
9486
config=config,
9587
)
96-
need_restart |= mta_sts_config.changed
9788

9889
# install CGI newemail script
9990
#
@@ -105,13 +96,9 @@ def _configure_nginx(config: Config, debug: bool = False) -> bool:
10596
group="root",
10697
)
10798

108-
files.put(
99+
deployer.put_file(
109100
name="Upload cgi newemail.py script",
110101
src=get_resource("newemail.py", pkg="chatmaild").open("rb"),
111102
dest=f"{cgi_dir}/newemail.py",
112-
user="root",
113-
group="root",
114-
mode="755",
103+
executable=True,
115104
)
116-
117-
return need_restart

0 commit comments

Comments
 (0)