-
-
Notifications
You must be signed in to change notification settings - Fork 62
automate and improve change-tracking in deployers #869
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,7 @@ | |||||
| from contextlib import contextmanager | ||||||
|
|
||||||
| from pyinfra import host | ||||||
| from pyinfra.facts.files import Sha256File | ||||||
| from pyinfra.facts.server import Command | ||||||
| from pyinfra.operations import files, server, systemd | ||||||
|
|
||||||
|
|
@@ -50,11 +51,10 @@ def get_resource(arg, pkg=__package__): | |||||
| return importlib.resources.files(pkg).joinpath(arg) | ||||||
|
|
||||||
|
|
||||||
| def configure_remote_units(mail_domain, units) -> None: | ||||||
| def configure_remote_units(deployer, mail_domain, units) -> None: | ||||||
| remote_base_dir = "/usr/local/lib/chatmaild" | ||||||
| remote_venv_dir = f"{remote_base_dir}/venv" | ||||||
| remote_chatmail_inipath = f"{remote_base_dir}/chatmail.ini" | ||||||
| root_owned = dict(user="root", group="root", mode="644") | ||||||
|
|
||||||
| # install systemd units | ||||||
| for fn in units: | ||||||
|
|
@@ -70,15 +70,13 @@ def configure_remote_units(mail_domain, units) -> None: | |||||
| source_path = get_resource(f"service/{basename}.f") | ||||||
| content = source_path.read_text().format(**params).encode() | ||||||
|
|
||||||
| files.put( | ||||||
| name=f"Upload {basename}", | ||||||
| deployer.put_file( | ||||||
| src=io.BytesIO(content), | ||||||
| dest=f"/etc/systemd/system/{basename}", | ||||||
| **root_owned, | ||||||
| ) | ||||||
|
|
||||||
|
|
||||||
| def activate_remote_units(units) -> None: | ||||||
| def activate_remote_units(deployer, units) -> None: | ||||||
| # activate systemd units | ||||||
| for fn in units: | ||||||
| basename = fn if "." in fn else f"{fn}.service" | ||||||
|
|
@@ -88,14 +86,8 @@ def activate_remote_units(units) -> None: | |||||
| enabled = False | ||||||
| else: | ||||||
| enabled = True | ||||||
| systemd.service( | ||||||
| name=f"Setup {basename}", | ||||||
| service=basename, | ||||||
| running=enabled, | ||||||
| enabled=enabled, | ||||||
| restarted=enabled, | ||||||
| daemon_reload=True, | ||||||
| ) | ||||||
|
|
||||||
| deployer.ensure_service(basename, running=enabled, enabled=enabled) | ||||||
|
|
||||||
|
|
||||||
| class Deployment: | ||||||
|
|
@@ -141,6 +133,7 @@ def perform_stages(self, deployers): | |||||
|
|
||||||
| class Deployer: | ||||||
| need_restart = False | ||||||
| daemon_reload = False | ||||||
|
|
||||||
| def install(self): | ||||||
| pass | ||||||
|
|
@@ -150,3 +143,113 @@ def configure(self): | |||||
|
|
||||||
| def activate(self): | ||||||
| pass | ||||||
|
|
||||||
| def ensure_service(self, service, running=True, enabled=True): | ||||||
| if running: | ||||||
| verb = "Start and enable" | ||||||
| else: | ||||||
| verb = "Stop" | ||||||
| systemd.service( | ||||||
| name=f"{verb} {service}", | ||||||
| service=service, | ||||||
| running=running, | ||||||
| enabled=enabled, | ||||||
| restarted=self.need_restart if running else False, | ||||||
| daemon_reload=self.daemon_reload, | ||||||
| ) | ||||||
| self.daemon_reload = False | ||||||
|
|
||||||
| def ensure_systemd_unit(self, src, **kwargs): | ||||||
| dest_name = src.split("/")[-1].replace(".j2", "") | ||||||
| dest = f"/etc/systemd/system/{dest_name}" | ||||||
| if src.endswith(".j2"): | ||||||
| return self.put_template(src, dest, **kwargs) | ||||||
| return self.put_file(src, dest) | ||||||
|
|
||||||
| def put_file(self, src, dest, mode="644"): | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think it would be valuable to preserve the ability to explain changes for put_file, put_template, remove_file, and embed it in braces into the name parameter.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. also, this takes mode as an argument, but template doesnt, but takes owner - maybe this should be symmetrical to be less confusing.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The new API is meant to only consists of things that map the previous usage, nothing more. If some other argument is needed, it is easy enough to add when it is actually needed. |
||||||
| if isinstance(src, str): | ||||||
| src = get_resource(src) | ||||||
| res = files.put( | ||||||
| name=f"Upload {dest}", | ||||||
| src=src, | ||||||
| dest=dest, | ||||||
| user="root", | ||||||
| group="root", | ||||||
| mode=mode, | ||||||
| ) | ||||||
|
|
||||||
| return self._update_restart_signals(dest, res) | ||||||
|
|
||||||
| def put_executable(self, src, dest): | ||||||
| return self.put_file(src, dest, mode="755") | ||||||
|
|
||||||
| def put_template(self, src, dest, owner="root", **kwargs): | ||||||
| if isinstance(src, str): | ||||||
| src = get_resource(src) | ||||||
| res = files.template( | ||||||
| name=f"Upload {dest}", | ||||||
| src=src, | ||||||
| dest=dest, | ||||||
| user=owner, | ||||||
| group=owner, | ||||||
| mode="644", | ||||||
| **kwargs, | ||||||
| ) | ||||||
|
|
||||||
| return self._update_restart_signals(dest, res) | ||||||
|
|
||||||
| def remove_file(self, dest): | ||||||
| res = files.file(name=f"Remove {dest}", path=dest, present=False) | ||||||
| return self._update_restart_signals(dest, res) | ||||||
|
|
||||||
| def ensure_line(self, path, line, **kwargs): | ||||||
| name = kwargs.pop("name", f"Ensure line in {path}") | ||||||
| res = files.line(name=name, path=path, line=line, **kwargs) | ||||||
| return self._update_restart_signals(path, res) | ||||||
|
|
||||||
| def ensure_directory(self, path, owner="root", mode="755", **kwargs): | ||||||
| name = kwargs.pop("name", f"Ensure directory {path}") | ||||||
| res = files.directory( | ||||||
| name=name, | ||||||
| path=path, | ||||||
| user=owner, | ||||||
| group=owner, | ||||||
| mode=mode, | ||||||
| present=True, | ||||||
| **kwargs, | ||||||
| ) | ||||||
| return self._update_restart_signals(path, res) | ||||||
|
|
||||||
| def remove_directory(self, path, **kwargs): | ||||||
| name = kwargs.pop("name", f"Remove directory {path}") | ||||||
| res = files.directory(name=name, path=path, present=False, **kwargs) | ||||||
| return self._update_restart_signals(path, res) | ||||||
|
|
||||||
| def download_executable(self, url, dest, sha256sum, extract=None): | ||||||
| existing = host.get_fact(Sha256File, dest) | ||||||
| if existing == sha256sum: | ||||||
| return | ||||||
|
|
||||||
| tmp = f"{dest}.new" | ||||||
| if extract: | ||||||
| dl_cmd = f"curl -fSL {url} | {extract} >{tmp}" | ||||||
| else: | ||||||
| dl_cmd = f"curl -fSL {url} -o {tmp}" | ||||||
|
|
||||||
| server.shell( | ||||||
| name=f"Download {dest}", | ||||||
| commands=[ | ||||||
| f"({dl_cmd}" | ||||||
| f" && echo '{sha256sum} {tmp}' | sha256sum -c" | ||||||
| f" && mv {tmp} {dest})", | ||||||
| f"chmod 755 {dest}", | ||||||
| ], | ||||||
| ) | ||||||
| self.need_restart = True | ||||||
|
|
||||||
| def _update_restart_signals(self, path, res): | ||||||
| if res.changed: | ||||||
| self.need_restart = True | ||||||
| if str(path).startswith("/etc/systemd/system/"): | ||||||
| self.daemon_reload = True | ||||||
| return res | ||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we should pass kwargs to the non-template-case, to honor
dest_namefor example.