pyinfra-dev / pyinfra

pyinfra turns Python code into shell commands and runs them on your servers. Execute ad-hoc commands and write declarative operations. Target SSH servers, local machine and Docker containers. Fast and scales from one server to thousands.
https://pyinfra.com
MIT License
3.91k stars 382 forks source link

Cannot _sudo_user as postgres after installing the package #1020

Closed snapeuh closed 8 months ago

snapeuh commented 1 year ago

Hey,

I am using pyinfra to provision our servers to host our app and there is a recurring problem I bump into that I cannot understand how to bypass unless creating two .py and run them one by one.

Here's my code :

from pyinfra.operations import apt,server,postgresql

# Postgres installation
apt.packages(
    name="Install postgres",
    packages=[
        "postgresql",
        "postgresql-client",
    ],
)

# Create postgres user & database
postgresql.role(
    name="Create dbroot user",
    role="root",
    password="password",
    superuser=True,
    createdb=True,
    createrole=True,
    _sudo_user="postgres",
)

postgresql.database(
    name="Create db database",
    database="db",
    owner="root",
    encoding="UTF8",
    _sudo_user="postgres",
)

server.service(
    name="Restart postgresql",
    service="postgresql",
    restarted=True,
)

Which looks a lot like the example provided in the doc : https://github.com/pyinfra-dev/pyinfra/blob/2.x/examples/postgresql.py

However, when doing this I got this error :

[host] sudo: unknown user postgres
[host] sudo: error initializing audit plugin sudoers_audit 
[host] Error: could not load fact: postgresql.PostgresqlRoles psql_host=None, psql_password=None, psql_port=None, psql_user=None

It tries to get fact about an user that isn't created yet but will be created. How to effectively deal with this ?

Thanks a lot.

snapeuh commented 1 year ago

I came accross this answer by @Fizzadar on reddit :

This should indeed work! I replied on GitHub; in short the auth escalation arguments sudo_user/su_user require the users to exist before running pyinfra.

But then I don't understand how the provided example should be working ?

Thanks for the help !

Fizzadar commented 1 year ago

🤦 the regex here has an extra colon on the end: https://github.com/pyinfra-dev/pyinfra/blob/7540c41fa0284b8dd80dcbea24d3616414484d60/pyinfra/api/facts.py#L40

Fizzadar commented 8 months ago

Fixed: https://github.com/pyinfra-dev/pyinfra/commit/924e6444cbedbd125f7baa048600ef74d5c36ad2, released in v2.9.1 just now.