forked from lab-in-a-box/liab-deployments
220 lines
5.4 KiB
Python
220 lines
5.4 KiB
Python
from pathlib import Path
|
|
|
|
from pyinfra.api import deploy
|
|
from pyinfra import (
|
|
host,
|
|
)
|
|
from pyinfra.operations import (
|
|
files,
|
|
server,
|
|
systemd,
|
|
)
|
|
|
|
from liab_deployments.operations import (
|
|
caddy,
|
|
user,
|
|
user_systemd,
|
|
)
|
|
|
|
# TODO without a static site, the --root-path must not be set to `api/`
|
|
service_unit_tmpl = """\
|
|
[Unit]
|
|
Description=DumpThings service
|
|
Wants=network-online.target
|
|
After=network-online.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
{service_params}
|
|
WorkingDirectory={user_home}
|
|
# we use inline script to be able to amend the PATH
|
|
ExecStart=bash -c "PATH={user_home}/.local/bin:$PATH; \\
|
|
dump-things-service \\
|
|
--port {host_port} \\
|
|
--config {config_filename} \\
|
|
--root-path /api \\
|
|
{service_args} \\
|
|
{user_home}/{data_dir} \\
|
|
"
|
|
|
|
[Install]
|
|
WantedBy=default.target
|
|
"""
|
|
|
|
caddy_config_tmpl = """\
|
|
{serve_address} {{
|
|
reverse_proxy localhost:{host_port}
|
|
}}
|
|
"""
|
|
|
|
|
|
caddy_config_w_staticsite_tmpl = """\
|
|
{serve_address} {{
|
|
handle_path /api/* {{
|
|
reverse_proxy localhost:{host_port}
|
|
}}
|
|
|
|
handle {{
|
|
root * {staticsite_root_dir}/
|
|
file_server
|
|
}}
|
|
}}
|
|
"""
|
|
|
|
# TODO make a parameter with this default
|
|
dumpthings_collections_config = """\
|
|
type: collections
|
|
version: 1
|
|
"""
|
|
|
|
|
|
@deploy("Deploy dumpthings")
|
|
def deploy_sites():
|
|
"""
|
|
Installing multiple dumpthings sites using different versions under
|
|
the same user account is not supported.
|
|
"""
|
|
if not hasattr(host.data, 'dumpthings'):
|
|
return
|
|
for spec in host.data.dumpthings.get('sites', []):
|
|
staticsite_root_dir = spec.get('staticsite_root_dir')
|
|
caddyfile_block_tmpl = spec.get('caddyfile_block_tmpl')
|
|
if caddyfile_block_tmpl is None:
|
|
caddyfile_block_tmpl = caddy_config_w_staticsite_tmpl \
|
|
if staticsite_root_dir else caddy_config_tmpl
|
|
kwargs = {
|
|
k: spec.get(k)
|
|
for k in (
|
|
'service_args',
|
|
'systemd_service_params',
|
|
'python_version',
|
|
'dumpthings_version',
|
|
)
|
|
}
|
|
_deploy_site(
|
|
spec['serve_address'],
|
|
spec['config_file_asset'],
|
|
spec['user'],
|
|
spec['host_port'],
|
|
spec['collections'],
|
|
data_dir=spec.get('data_dir', 'data'),
|
|
name=spec.get('name', 'dumpthings'),
|
|
caddyfile_block_tmpl=caddyfile_block_tmpl,
|
|
staticsite_root_dir=staticsite_root_dir,
|
|
**kwargs
|
|
)
|
|
|
|
|
|
def _deploy_site(
|
|
serve_address: str,
|
|
config_file_asset: str,
|
|
user_spec: tuple[str, int],
|
|
host_port: int,
|
|
collections: list[tuple],
|
|
*,
|
|
data_dir: str,
|
|
name: str,
|
|
caddyfile_block_tmpl: str,
|
|
service_args: str | None = None,
|
|
systemd_service_params: str,
|
|
dumpthings_version: str | None = None,
|
|
python_version: str | None = None,
|
|
staticsite_root_dir: str | None = None,
|
|
):
|
|
user_name, uid = user_spec
|
|
user_home = f'/home/{user_name}'
|
|
|
|
config_file = f'{user_home}/{name}_config.yaml'
|
|
|
|
user.systemd_service(
|
|
user_name,
|
|
uid,
|
|
user_home,
|
|
)
|
|
|
|
user.uv(
|
|
user_name,
|
|
)
|
|
|
|
pyarg = f"--python {python_version}" if python_version else ""
|
|
dtarg = f'dump-things-service{dumpthings_version or ""}'
|
|
server.shell(
|
|
name=f'Install dump-things-service {name!r}',
|
|
commands=[
|
|
f"$HOME/.local/bin/uv tool install {pyarg} {dtarg}"
|
|
],
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
for i in [data_dir] + [f'{data_dir}/{c[0]}' for c in collections]:
|
|
files.directory(
|
|
path=f'{user_home}/{i}',
|
|
present=True,
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
user_systemd.service_unit(
|
|
user_name,
|
|
user_home,
|
|
name,
|
|
service_unit_tmpl.format(
|
|
user_home=user_home,
|
|
host_port=host_port,
|
|
service_params=systemd_service_params or '',
|
|
service_args=service_args or '',
|
|
config_filename=config_file,
|
|
data_dir=data_dir,
|
|
),
|
|
)
|
|
|
|
files.block(
|
|
name='Dump-things API config',
|
|
path=config_file,
|
|
content=Path(config_file_asset).read_text(),
|
|
present=True,
|
|
try_prevent_shell_expansion=True,
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
files.block(
|
|
name='Dump-things collections config',
|
|
path=f'{user_home}/{data_dir}/.dumpthings.yaml',
|
|
content=dumpthings_collections_config,
|
|
present=True,
|
|
try_prevent_shell_expansion=True,
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
for c in collections:
|
|
if not c[1]:
|
|
continue
|
|
files.block(
|
|
name=f'Dump-things "{c[0]}" collection config',
|
|
path=f'{user_home}/{data_dir}/{c[0]}/.dumpthings.yaml',
|
|
content=Path(c[1]).read_text(),
|
|
present=True,
|
|
try_prevent_shell_expansion=True,
|
|
_sudo_user=user_name,
|
|
)
|
|
|
|
user_systemd.run_service(
|
|
user_name,
|
|
uid,
|
|
name,
|
|
)
|
|
|
|
server.wait(
|
|
name=f"Wait for dumpthings {serve_address!r} to start",
|
|
port=host_port,
|
|
)
|
|
|
|
caddyfile_block_params = {
|
|
'serve_address': serve_address,
|
|
'host_port': host_port,
|
|
}
|
|
if staticsite_root_dir:
|
|
caddyfile_block_params['staticsite_root_dir'] = staticsite_root_dir
|
|
caddy.caddyfile_block(
|
|
marker=f'DUMPTHINGS {serve_address}',
|
|
content=caddyfile_block_tmpl.format(**caddyfile_block_params),
|
|
)
|