add stuff
This commit is contained in:
parent
0fcec72f21
commit
5122caf74f
9 changed files with 706 additions and 0 deletions
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
|||
privy==6.0.0
|
27
tasks/aproxy.py
Normal file
27
tasks/aproxy.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
from pyinfra import host
|
||||
from pyinfra.operations import dnf, server, files, systemd, postgresql
|
||||
from pyinfra.api import deploy
|
||||
from pyinfra.facts.server import Which
|
||||
|
||||
from .operations.git import repo
|
||||
|
||||
|
||||
@deploy("install aproxy")
|
||||
def install():
|
||||
main_path = "/opt/aproxy"
|
||||
repo_output = repo(
|
||||
name="clone aproxy repo",
|
||||
src="https://gitdab.com/luna/aproxy",
|
||||
dest=f"{main_path}/src",
|
||||
branch="mistress",
|
||||
)
|
||||
|
||||
config_directory = "/etc/aproxy"
|
||||
files.directory(config_directory)
|
||||
remote_config_path = f"{config_directory}/conf.lua"
|
||||
config_output = files.template(
|
||||
"./files/aproxy/conf.lua.j2",
|
||||
dest=remote_config_path,
|
||||
mode=555,
|
||||
cfg=host.data,
|
||||
)
|
28
tasks/croc.py
Normal file
28
tasks/croc.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
from packaging import version
|
||||
from pyinfra.operations import apk, server, files
|
||||
from pyinfra.facts.server import LinuxName
|
||||
from pyinfra.api import deploy
|
||||
from pyinfra import host
|
||||
|
||||
CROC_ALPINE_VERSION = version.parse("3.14")
|
||||
|
||||
|
||||
@deploy("install croc")
|
||||
def install_croc():
|
||||
|
||||
# alpine provides croc in-repo as of 3.14
|
||||
if host.get_fact(LinuxName) == "Alpine":
|
||||
host_alpine_version = version.parse(host.data.alpine_version)
|
||||
if host_alpine_version >= CROC_ALPINE_VERSION:
|
||||
apk.packages(name="install croc via apk", packages=["croc"])
|
||||
return
|
||||
|
||||
# for everyone else, install manually
|
||||
files.directory("/opt/croc")
|
||||
files.download(
|
||||
"https://github.com/schollz/croc/releases/download/v9.6.3/croc_9.6.3_Linux-64bit.tar.gz",
|
||||
"/opt/croc/croc.tar.gz",
|
||||
md5sum="5550b0bfb50d0541cba790562c180bd7",
|
||||
)
|
||||
server.shell("tar xvf /opt/croc/croc.tar.gz", _chdir="/opt/croc")
|
||||
server.shell("mv /opt/croc/croc /usr/bin/croc", _chdir="/opt/croc")
|
172
tasks/docker.py
Normal file
172
tasks/docker.py
Normal file
|
@ -0,0 +1,172 @@
|
|||
import logging
|
||||
import subprocess
|
||||
import json
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
from pyinfra import host
|
||||
from pyinfra.api import deploy, FactBase, operation, FunctionCommand
|
||||
from pyinfra.operations import files, apt, dnf, systemd, python, server
|
||||
from pyinfra.facts.server import LinuxName
|
||||
from .install_consul_server import template_and_install_systemd
|
||||
|
||||
|
||||
DEFAULTS = {
|
||||
"docker_registry_image": "registry:2.8.1",
|
||||
}
|
||||
|
||||
|
||||
@deploy("install docker")
|
||||
def install_docker():
|
||||
linux_name = host.get_fact(LinuxName)
|
||||
if linux_name == "Fedora":
|
||||
dnf.packages(["docker", "docker-compose"])
|
||||
systemd.service("docker", enabled=True, running=True)
|
||||
else:
|
||||
apt.packages(["docker.io", "docker-compose"])
|
||||
|
||||
|
||||
class TailscaleIPs(FactBase):
|
||||
requires_command = "tailscale"
|
||||
command = "tailscale ip"
|
||||
|
||||
def process(self, output):
|
||||
# TODO provide ipaddress for nicer formatting in conf tools
|
||||
for line in output:
|
||||
if ":" in line:
|
||||
continue
|
||||
return [line]
|
||||
|
||||
|
||||
class DockerImage(FactBase):
|
||||
requires_command = "docker"
|
||||
|
||||
def command(self, object_id):
|
||||
return f"docker image inspect {object_id} || true"
|
||||
|
||||
def process(self, output):
|
||||
joined_out = "".join(output)
|
||||
return json.loads(joined_out)
|
||||
|
||||
|
||||
class DockerManifestInspect(FactBase):
|
||||
requires_command = "docker"
|
||||
|
||||
def command(self, object_id):
|
||||
return f"docker image inspect {object_id} || true"
|
||||
|
||||
def process(self, output):
|
||||
if "no such manifest" in output:
|
||||
return None
|
||||
joined_out = "".join(output)
|
||||
return json.loads(joined_out)
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def docker_image_from_host_to_target(image_reference: str):
|
||||
assert image_reference
|
||||
|
||||
username = host.data.ssh_user
|
||||
hostname = host.name
|
||||
|
||||
log.warning(
|
||||
"hello, sending image %r to host %s@%s", image_reference, username, hostname
|
||||
)
|
||||
|
||||
with tempfile.NamedTemporaryFile() as f:
|
||||
cmdline = f"docker save {image_reference} | gzip | pv > {f.name}"
|
||||
log.warning("exec %r", cmdline)
|
||||
subprocess.check_output(cmdline, shell=True)
|
||||
|
||||
with subprocess.Popen(["croc", "send", f.name], stderr=subprocess.PIPE) as proc:
|
||||
transfer_code = None
|
||||
for line_in in proc.stderr:
|
||||
line = line_in.decode()
|
||||
log.warning("got stdin line: %r", line)
|
||||
TRANSFER_CODE_PHRASE = "Code is: "
|
||||
transfer_code_index = line.find(TRANSFER_CODE_PHRASE)
|
||||
if transfer_code_index == -1:
|
||||
continue
|
||||
transfer_code = line[
|
||||
transfer_code_index + len(TRANSFER_CODE_PHRASE) :
|
||||
].strip()
|
||||
assert len(transfer_code) > 10
|
||||
log.warning("extracted transfer code: %r", transfer_code)
|
||||
break
|
||||
assert transfer_code
|
||||
|
||||
target_path = Path(f.name).name
|
||||
send_cmdline = f"croc --yes {transfer_code}"
|
||||
server.shell(send_cmdline, _chdir="/tmp")
|
||||
server.shell(
|
||||
f"cat {target_path} | docker load", _chdir="/tmp", name="load image file"
|
||||
)
|
||||
server.shell(f"rm /tmp/{target_path}", name="remove image file after importing")
|
||||
|
||||
|
||||
@operation
|
||||
def docker_image(image_reference: str):
|
||||
images = host.get_fact(DockerImage, image_reference)
|
||||
if not images:
|
||||
name, *_version = image_reference.split(":")
|
||||
if name in host.data.manual_docker_images:
|
||||
# get it from my machine lmao
|
||||
log.warning(
|
||||
"this deploy script wants image %r, taking it from host system and sending it",
|
||||
image_reference,
|
||||
)
|
||||
yield FunctionCommand(
|
||||
docker_image_from_host_to_target, (image_reference,), {}
|
||||
)
|
||||
else:
|
||||
# take it from given image ref
|
||||
yield f"docker pull {image_reference}"
|
||||
|
||||
|
||||
def template_and_install_compose(
|
||||
compose_template_path: str,
|
||||
env_dict: Optional[dict] = None,
|
||||
*,
|
||||
systemd_service: Optional[str] = None,
|
||||
):
|
||||
env_dict = env_dict or {}
|
||||
compose_template = Path(compose_template_path)
|
||||
systemd_service = systemd_service or compose_template.name.split(".")[0]
|
||||
assert systemd_service != "compose"
|
||||
assert systemd_service.endswith(".service")
|
||||
|
||||
systemd_service_name = systemd_service.split(".")[0]
|
||||
|
||||
working_directory = f"/opt/{systemd_service_name}"
|
||||
|
||||
files.template(
|
||||
compose_template_path,
|
||||
f"{working_directory}/compose.yaml",
|
||||
env_dict=env_dict,
|
||||
name=f"sending compose file {systemd_service_name}",
|
||||
)
|
||||
|
||||
template_and_install_systemd(
|
||||
"files/compose.service.j2",
|
||||
env_dict={
|
||||
"service_name": systemd_service_name,
|
||||
"working_directory": working_directory,
|
||||
},
|
||||
service_name=systemd_service,
|
||||
)
|
||||
|
||||
|
||||
@deploy("install docker registry", data_defaults=DEFAULTS)
|
||||
def install_registry():
|
||||
install_docker()
|
||||
docker_image(host.data.docker_registry_image)
|
||||
template_and_install_compose(
|
||||
"files/registry/compose.yaml.j2",
|
||||
{
|
||||
"docker_registry_image": host.data.docker_registry_image,
|
||||
},
|
||||
systemd_service="registry.service",
|
||||
)
|
76
tasks/elixir.py
Normal file
76
tasks/elixir.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
from typing import Optional
|
||||
from pyinfra import host
|
||||
from pyinfra.api import deploy
|
||||
from pyinfra.operations import apt, files, server, dnf
|
||||
from pyinfra.facts.server import LinuxName
|
||||
from pyinfra.facts import server as server_facts
|
||||
|
||||
|
||||
ELIXIR_DEFAULTS = {
|
||||
"elixir_version": "1.13.4",
|
||||
"erlang_version": "25",
|
||||
}
|
||||
|
||||
|
||||
def install_for_ubuntu():
|
||||
elixir_is_updated = False
|
||||
erlang_is_updated = False
|
||||
|
||||
wanted_elixir_version = host.data.elixir_version
|
||||
wanted_erlang_version = host.data.erlang_version
|
||||
|
||||
elixir_command = host.get_fact(server_facts.Which, command="elixir")
|
||||
if elixir_command:
|
||||
elixir_version = host.get_fact(ElixirVersion)
|
||||
elixir_is_updated = elixir_version == wanted_elixir_version
|
||||
|
||||
erlang_command = host.get_fact(server_facts.Which, command="erl")
|
||||
if erlang_command:
|
||||
erlang_version = host.get_fact(ErlangVersion)
|
||||
erlang_is_updated = erlang_version == wanted_erlang_version
|
||||
|
||||
if elixir_is_updated and erlang_is_updated:
|
||||
return
|
||||
|
||||
# elixir is non trivial to install because we can't
|
||||
# rely on the ubuntu package repo to be updated
|
||||
#
|
||||
# so we use the Erlang Solutions repository as recommended by elixir themselves.
|
||||
|
||||
erlang_repo_deb_path = "/tmp/erlang-solutions.deb"
|
||||
files.download(
|
||||
name="download erlang solutions repo deb file",
|
||||
src="https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb",
|
||||
dest=erlang_repo_deb_path,
|
||||
)
|
||||
|
||||
apt.deb(
|
||||
name="install erlang solutions repo",
|
||||
src=erlang_repo_deb_path,
|
||||
)
|
||||
|
||||
# TODO: we don't need to update if we already installed the deb
|
||||
apt.update(cache_time=3600)
|
||||
|
||||
# its in two separate steps as recommended by readme. who am i to judge
|
||||
apt.packages(
|
||||
name="install erlang",
|
||||
packages=[
|
||||
f"erlang={otp_version}" if otp_version else f"erlang",
|
||||
f"erlang-manpages={otp_version}" if otp_version else f"erlang-manpages",
|
||||
],
|
||||
)
|
||||
apt.packages(
|
||||
name="install elixir",
|
||||
packages=[f"elixir={elixir_version}" if elixir_version else "elixir"],
|
||||
)
|
||||
|
||||
|
||||
@deploy("Install Elixir", data_defaults=ELIXIR_DEFAULTS)
|
||||
def install():
|
||||
linux_name = host.get_fact(LinuxName)
|
||||
if linux_name == "Fedora":
|
||||
dnf.packages(["erlang", "elixir"])
|
||||
else:
|
||||
install_for_ubuntu()
|
||||
server.shell(name="test elixir exists", commands=["elixir -v"])
|
163
tasks/operations/git.py
Normal file
163
tasks/operations/git.py
Normal file
|
@ -0,0 +1,163 @@
|
|||
from pyinfra.operations import apk, files, server, git, systemd, python
|
||||
from pyinfra import host
|
||||
|
||||
from pyinfra.facts.files import Directory
|
||||
from pyinfra.facts.git import GitBranch
|
||||
|
||||
from pyinfra.api import deploy, operation, FactBase
|
||||
from pyinfra.operations.util.files import chown, unix_path_join
|
||||
|
||||
|
||||
class CoolerGitBranch(FactBase):
|
||||
requires_command = "git"
|
||||
|
||||
@staticmethod
|
||||
def command(repo):
|
||||
# TODO should inject _sudo / _sudo_user if user is provided in repo()
|
||||
return "! test -d {0} || (cd {0} && git rev-parse --abbrev-ref HEAD)".format(
|
||||
repo
|
||||
)
|
||||
|
||||
|
||||
class GitFetch(FactBase):
|
||||
def command(self, repo: str):
|
||||
return f"git -C {repo} fetch"
|
||||
|
||||
def process(self, output):
|
||||
return output
|
||||
|
||||
|
||||
class GitRevListComparison(FactBase):
|
||||
def command(self, repo: str, branch: str):
|
||||
return f"git -C {repo} rev-list HEAD..origin/{branch} | wc -l"
|
||||
|
||||
def process(self, output):
|
||||
return output
|
||||
|
||||
|
||||
class RawCommandOutput(FactBase):
|
||||
"""
|
||||
Returns the raw output of a command.
|
||||
"""
|
||||
|
||||
def command(self, command):
|
||||
return command
|
||||
|
||||
def process(self, output):
|
||||
return "\n".join(output) # re-join and return the output lines
|
||||
|
||||
|
||||
@operation(
|
||||
pipeline_facts={
|
||||
"git_branch": "target",
|
||||
}
|
||||
)
|
||||
def repo(
|
||||
src,
|
||||
dest,
|
||||
branch=None,
|
||||
pull=True,
|
||||
rebase=False,
|
||||
user=None,
|
||||
group=None,
|
||||
ssh_keyscan=False,
|
||||
update_submodules=False,
|
||||
recursive_submodules=False,
|
||||
):
|
||||
"""
|
||||
Clone/pull git repositories.
|
||||
|
||||
+ src: the git source URL
|
||||
+ dest: directory to clone to
|
||||
+ branch: branch to pull/checkout
|
||||
+ pull: pull any changes for the branch
|
||||
+ rebase: when pulling, use ``--rebase``
|
||||
+ user: chown files to this user after
|
||||
+ group: chown files to this group after
|
||||
+ ssh_keyscan: keyscan the remote host if not in known_hosts before clone/pull
|
||||
+ update_submodules: update any git submodules
|
||||
+ recursive_submodules: update git submodules recursively
|
||||
|
||||
Example:
|
||||
|
||||
.. code:: python
|
||||
|
||||
git.repo(
|
||||
name='Clone repo',
|
||||
src='https://github.com/Fizzadar/pyinfra.git',
|
||||
dest='/usr/local/src/pyinfra',
|
||||
)
|
||||
"""
|
||||
|
||||
# Ensure our target directory exists
|
||||
yield from files.directory(dest)
|
||||
|
||||
if ssh_keyscan:
|
||||
raise NotImplementedError("TODO copypaste ssh_keyscan code")
|
||||
|
||||
# Store git commands for directory prefix
|
||||
git_commands = []
|
||||
git_dir = unix_path_join(dest, ".git")
|
||||
is_repo = host.get_fact(Directory, path=git_dir)
|
||||
|
||||
# Cloning new repo?
|
||||
if not is_repo:
|
||||
if branch:
|
||||
git_commands.append("clone {0} --branch {1} .".format(src, branch))
|
||||
else:
|
||||
git_commands.append("clone {0} .".format(src))
|
||||
|
||||
host.create_fact(GitBranch, kwargs={"repo": dest}, data=branch)
|
||||
host.create_fact(CoolerGitBranch, kwargs={"repo": dest}, data=branch)
|
||||
host.create_fact(
|
||||
Directory,
|
||||
kwargs={"path": git_dir},
|
||||
data={"user": user, "group": group},
|
||||
)
|
||||
|
||||
# Ensuring existing repo
|
||||
else:
|
||||
current_branch = host.get_fact(CoolerGitBranch, repo=dest)
|
||||
|
||||
# always fetch upstream branches (that way we can compare if the latest
|
||||
# commit has changed, and then we don't need to execute anything!)
|
||||
host.get_fact(GitFetch, repo=dest)
|
||||
stdout = host.get_fact(GitRevListComparison, repo=dest, branch=branch)
|
||||
repository_has_updates = stdout[0] != "0"
|
||||
|
||||
# since we immediately always fetch, we will always be modifying the
|
||||
# .git folder, and that folder MUST be owned by the correct user afterwards.
|
||||
if user or group:
|
||||
chown_command = chown(dest, user, group, recursive=True)
|
||||
host.get_fact(RawCommandOutput, command=chown_command.get_masked_value())
|
||||
|
||||
if branch and current_branch != branch:
|
||||
git_commands.append("checkout {0}".format(branch))
|
||||
host.create_fact(GitBranch, kwargs={"repo": dest}, data=branch)
|
||||
host.create_fact(CoolerGitBranch, kwargs={"repo": dest}, data=branch)
|
||||
repository_has_updates = True
|
||||
|
||||
if repository_has_updates and pull:
|
||||
if rebase:
|
||||
git_commands.append("pull --rebase")
|
||||
else:
|
||||
git_commands.append("pull")
|
||||
|
||||
if update_submodules:
|
||||
if recursive_submodules:
|
||||
git_commands.append("submodule update --init --recursive")
|
||||
else:
|
||||
git_commands.append("submodule update --init")
|
||||
|
||||
# Attach prefixes for directory
|
||||
command_prefix = "cd {0} && git".format(dest)
|
||||
git_commands = [
|
||||
"{0} {1}".format(command_prefix, command) for command in git_commands
|
||||
]
|
||||
|
||||
for cmd in git_commands:
|
||||
yield cmd
|
||||
|
||||
# Apply any user or group if we did anything
|
||||
if git_commands and (user or group):
|
||||
yield chown(dest, user, group, recursive=True)
|
184
tasks/pleroma.py
Normal file
184
tasks/pleroma.py
Normal file
|
@ -0,0 +1,184 @@
|
|||
from pyinfra import host
|
||||
from pyinfra.operations import dnf, server, files, systemd, postgresql
|
||||
from pyinfra.api import deploy
|
||||
from pyinfra.facts.server import Which
|
||||
|
||||
from .secrets import secrets
|
||||
from .operations.git import repo
|
||||
from tasks.elixir import install as install_elixir
|
||||
from .install_consul_server import template_and_install_systemd
|
||||
from tasks.rpmfusion import install as install_rpmfusion
|
||||
from tasks.postgresql import install as install_postgresql
|
||||
|
||||
|
||||
class WithSecrets:
|
||||
def __init__(self, secrets_fields):
|
||||
self._secrets_values = {}
|
||||
for field in secrets_fields:
|
||||
secret_value = secrets.field(field)
|
||||
self._secrets_values[field] = secret_value
|
||||
|
||||
def __getattr__(self, field):
|
||||
if field in self._secrets_values:
|
||||
return self._secrets_values[field]
|
||||
return getattr(host.data, field)
|
||||
|
||||
|
||||
@deploy("install pleroma")
|
||||
def install():
|
||||
install_elixir()
|
||||
install_rpmfusion()
|
||||
install_postgresql()
|
||||
|
||||
dnf.packages(
|
||||
name="install system depedencies",
|
||||
packages=[
|
||||
"sudo",
|
||||
"git",
|
||||
"make",
|
||||
"automake",
|
||||
"gcc",
|
||||
"gcc-c++",
|
||||
"kernel-devel",
|
||||
"cmake",
|
||||
"file-libs",
|
||||
"file-devel",
|
||||
"ImageMagick",
|
||||
"ImageMagick-libs",
|
||||
"ffmpeg",
|
||||
"perl-Image-ExifTool",
|
||||
"erlang-parsetools",
|
||||
],
|
||||
)
|
||||
|
||||
files.directory(path="/opt/pleroma", present=True, mode=755, recursive=True)
|
||||
runner_user = "pleroma"
|
||||
|
||||
server.group(runner_user)
|
||||
|
||||
remote_main_home_path = f"/opt/pleroma"
|
||||
remote_main_pleroma_path = f"/opt/pleroma/pleroma"
|
||||
|
||||
server.user(
|
||||
user=runner_user,
|
||||
present=True,
|
||||
home=remote_main_home_path,
|
||||
shell="/bin/false",
|
||||
group=runner_user,
|
||||
ensure_home=True,
|
||||
)
|
||||
|
||||
# commit pinning is done by having a separate branch on a mirror repo
|
||||
repo_output = repo(
|
||||
name="clone pleroma repo",
|
||||
src="https://gitlab.com/luna/pleroma.git",
|
||||
dest=remote_main_pleroma_path,
|
||||
branch="securomoe/develop",
|
||||
user=runner_user,
|
||||
group=runner_user,
|
||||
)
|
||||
|
||||
remote_config_path = f"{remote_main_pleroma_path}/config/prod.secret.exs"
|
||||
with_secrets = WithSecrets(
|
||||
(
|
||||
"pleroma_secret_key_base",
|
||||
"pleroma_db_password",
|
||||
"pleroma_webpush_public_key",
|
||||
"pleroma_webpush_private_key",
|
||||
)
|
||||
)
|
||||
config_output = files.template(
|
||||
"./files/pleroma/prod.secret.exs",
|
||||
dest=remote_config_path,
|
||||
user=runner_user,
|
||||
group=runner_user,
|
||||
mode=500,
|
||||
cfg=with_secrets,
|
||||
)
|
||||
|
||||
# download pleroma deps via mix
|
||||
server.shell(
|
||||
name="download pleroma deps",
|
||||
_chdir=remote_main_pleroma_path,
|
||||
_sudo=True,
|
||||
_sudo_user=runner_user,
|
||||
_env={"MIX_ENV": "prod"},
|
||||
commands=[
|
||||
"mix local.hex --if-missing --force",
|
||||
"mix local.rebar --if-missing --force",
|
||||
"mix deps.get",
|
||||
],
|
||||
)
|
||||
|
||||
# compile deps and compile pleroma
|
||||
server.shell(
|
||||
name="compile pleroma",
|
||||
_chdir=remote_main_pleroma_path,
|
||||
_sudo=True,
|
||||
_sudo_user=runner_user,
|
||||
_env={"MIX_ENV": "prod"},
|
||||
commands=["mix deps.compile", "mix compile"],
|
||||
)
|
||||
|
||||
# map the following sql script into pyinfra
|
||||
|
||||
# CREATE USER pleroma WITH ENCRYPTED PASSWORD 'aaa' CREATEDB;
|
||||
# CREATE DATABASE pleroma_dev;
|
||||
# ALTER DATABASE pleroma_dev OWNER TO pleroma;
|
||||
# \c pleroma_dev;
|
||||
# --Extensions made by ecto.migrate that need superuser access
|
||||
# CREATE EXTENSION IF NOT EXISTS citext;
|
||||
# CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||||
|
||||
# hacky as we need postgres user but also the fact will fail if postgres
|
||||
# isnt initialized...
|
||||
has_postgres = host.get_fact(Which, command="psql")
|
||||
postgres_kwargs = {}
|
||||
if has_postgres:
|
||||
postgres_kwargs = {"_sudo": True, "_sudo_user": "postgres"}
|
||||
|
||||
postgresql.role(
|
||||
role=host.data.pleroma_db_user,
|
||||
password=with_secrets.pleroma_db_password,
|
||||
login=True,
|
||||
**postgres_kwargs,
|
||||
)
|
||||
|
||||
db_result = postgresql.database(
|
||||
database=host.data.pleroma_db_name,
|
||||
owner=host.data.pleroma_db_user,
|
||||
encoding="UTF8",
|
||||
**postgres_kwargs,
|
||||
)
|
||||
|
||||
# is it possible to configure pg_hba.conf to add md5 auth to local v4/v6
|
||||
|
||||
if db_result.changed:
|
||||
postgresql.sql(
|
||||
"""
|
||||
CREATE EXTENSION IF NOT EXISTS citext;
|
||||
CREATE EXTENSION IF NOT EXISTS pg_trgm;
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
""",
|
||||
database=host.data.pleroma_db_name,
|
||||
**postgres_kwargs,
|
||||
)
|
||||
|
||||
server.shell(
|
||||
name="migrate database",
|
||||
_chdir=remote_main_pleroma_path,
|
||||
_sudo=True,
|
||||
_sudo_user=runner_user,
|
||||
_env={"MIX_ENV": "prod"},
|
||||
commands=["mix ecto.migrate"],
|
||||
)
|
||||
|
||||
template_and_install_systemd(
|
||||
"./files/pleroma/pleroma.service.j2",
|
||||
env_dict={
|
||||
"user": runner_user,
|
||||
"remote_main_home_path": remote_main_home_path,
|
||||
"remote_main_pleroma_path": remote_main_pleroma_path,
|
||||
},
|
||||
restarted=repo_output.changed or config_output.changed,
|
||||
)
|
42
tasks/postgresql.py
Normal file
42
tasks/postgresql.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
from typing import Optional
|
||||
from pyinfra import host
|
||||
from pyinfra.api import deploy
|
||||
from pyinfra.operations import dnf, systemd, server
|
||||
from pyinfra.facts.server import LinuxName, LinuxDistribution
|
||||
|
||||
|
||||
@deploy("Install PostgreSQL")
|
||||
def install():
|
||||
linux_name = host.get_fact(LinuxName)
|
||||
version = host.data.postgresql_version
|
||||
|
||||
if linux_name == "Fedora":
|
||||
fedora_release = host.get_fact(LinuxDistribution)["major"]
|
||||
dnf.rpm(
|
||||
f"https://download.postgresql.org/pub/repos/yum/reporpms/F-{fedora_release}-x86_64/pgdg-fedora-repo-latest.noarch.rpm"
|
||||
)
|
||||
|
||||
result = dnf.packages(
|
||||
name=f"Install psql {version} packages",
|
||||
packages=[
|
||||
f"postgresql{version}",
|
||||
f"postgresql{version}-server",
|
||||
f"postgresql{version}-contrib",
|
||||
],
|
||||
)
|
||||
|
||||
if result.changed:
|
||||
server.shell(
|
||||
name="initialize pgsql db",
|
||||
commands=[
|
||||
f"/usr/pgsql-{version}/bin/postgresql-{version}-setup initdb"
|
||||
],
|
||||
)
|
||||
|
||||
systemd.service(
|
||||
name="install psql {version} unit",
|
||||
service=f"postgresql-{version}",
|
||||
running=True,
|
||||
enabled=True,
|
||||
daemon_reload=True,
|
||||
)
|
13
tasks/rpmfusion.py
Normal file
13
tasks/rpmfusion.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
from pyinfra import host
|
||||
from pyinfra.api import deploy
|
||||
from pyinfra.operations import dnf
|
||||
from pyinfra.facts.server import LinuxDistribution
|
||||
|
||||
|
||||
@deploy("install RPM fusion")
|
||||
def install():
|
||||
fedora_release = host.get_fact(LinuxDistribution)["major"]
|
||||
free_url = f"https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-{fedora_release}.noarch.rpm"
|
||||
nonfree_url = f"https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-{fedora_release}.noarch.rpm"
|
||||
dnf.rpm(free_url)
|
||||
dnf.rpm(nonfree_url)
|
Loading…
Reference in a new issue