Esempi Pyinfra: differenze tra le versioni

Da GazziNet.
Vai alla navigazione Vai alla ricerca
(Espansione esempi Pyinfra con casi base e avanzati)
(Espansione esempi Pyinfra con casi base e avanzati)
Riga 14: Riga 14:
== Esempio base 1: esecuzione su host locali ==
== Esempio base 1: esecuzione su host locali ==
Se vuoi solo capire la CLI:
Se vuoi solo capire la CLI:
<syntaxhighlight lang="bash">
<pre>
pyinfra @local exec -- echo "hello world"
pyinfra @local exec -- echo "hello world"
</syntaxhighlight>
</pre>


Questo serve quando vuoi verificare:
Questo serve quando vuoi verificare:
Riga 24: Riga 24:


== Esempio base 2: inventory minimale ==
== Esempio base 2: inventory minimale ==
<syntaxhighlight lang="python">
<pre>
web_servers = [
web_servers = [
     "web-01.example.net",
     "web-01.example.net",
     "web-02.example.net",
     "web-02.example.net",
]
]
</syntaxhighlight>
</pre>


Qui hai solo una lista di host.
Qui hai solo una lista di host.


== Esempio base 3: operation semplice ==
== Esempio base 3: operation semplice ==
<syntaxhighlight lang="python">
<pre>
from pyinfra.operations import server
from pyinfra.operations import server


Riga 41: Riga 41:
     commands=["uptime"],
     commands=["uptime"],
)
)
</syntaxhighlight>
</pre>


Esecuzione:
Esecuzione:
<syntaxhighlight lang="bash">
<pre>
pyinfra inventory.py deploy.py
pyinfra inventory.py deploy.py
</syntaxhighlight>
</pre>


== Esempio base 4: installare pacchetti ==
== Esempio base 4: installare pacchetti ==
<syntaxhighlight lang="python">
<pre>
from pyinfra.operations import apt
from pyinfra.operations import apt


Riga 57: Riga 57:
     update=True,
     update=True,
)
)
</syntaxhighlight>
</pre>


Questo e un esempio di operation idempotente: se i pacchetti sono gia presenti, pyinfra non rifara cambiamenti inutili.
Questo e un esempio di operation idempotente: se i pacchetti sono gia presenti, pyinfra non rifara cambiamenti inutili.


== Esempio base 5: gestire file ==
== Esempio base 5: gestire file ==
<syntaxhighlight lang="python">
<pre>
from pyinfra.operations import files
from pyinfra.operations import files


Riga 72: Riga 72:
     mode="644",
     mode="644",
)
)
</syntaxhighlight>
</pre>


== Esempio base 6: gestire servizi ==
== Esempio base 6: gestire servizi ==
<syntaxhighlight lang="python">
<pre>
from pyinfra.operations import systemd
from pyinfra.operations import systemd


Riga 84: Riga 84:
     enabled=True,
     enabled=True,
)
)
</syntaxhighlight>
</pre>


== Esempio intermedio 1: dati host ==
== Esempio intermedio 1: dati host ==
Inventory:
Inventory:
<syntaxhighlight lang="python">
<pre>
app_servers = [
app_servers = [
     ("app-01.example.net", {"install_nginx": True}),
     ("app-01.example.net", {"install_nginx": True}),
     ("app-02.example.net", {"install_nginx": False}),
     ("app-02.example.net", {"install_nginx": False}),
]
]
</syntaxhighlight>
</pre>


Deploy:
Deploy:
<syntaxhighlight lang="python">
<pre>
from pyinfra import host
from pyinfra import host
from pyinfra.operations import apt
from pyinfra.operations import apt
Riga 106: Riga 106:
         update=True,
         update=True,
     )
     )
</syntaxhighlight>
</pre>


Qui usi Python per rendere il deploy diverso in base ai dati del target.
Qui usi Python per rendere il deploy diverso in base ai dati del target.


== Esempio intermedio 2: gruppi ==
== Esempio intermedio 2: gruppi ==
<syntaxhighlight lang="python">
<pre>
from pyinfra import host, local
from pyinfra import host, local
from pyinfra.operations import server
from pyinfra.operations import server
Riga 125: Riga 125:
     commands=["hostname"],
     commands=["hostname"],
)
)
</syntaxhighlight>
</pre>


Questo pattern e utile quando vuoi dividere la logica in file piu piccoli.
Questo pattern e utile quando vuoi dividere la logica in file piu piccoli.
Riga 132: Riga 132:
Questo e il pattern usato nel progetto Proxmox Web UI: pyinfra gira su <code>@local</code> ma esegue un helper esterno che contiene la logica vera.
Questo e il pattern usato nel progetto Proxmox Web UI: pyinfra gira su <code>@local</code> ma esegue un helper esterno che contiene la logica vera.


<syntaxhighlight lang="python">
<pre>
#!/usr/bin/env python3
#!/usr/bin/env python3
import os
import os
Riga 149: Riga 149:
     commands=[cmd],
     commands=[cmd],
)
)
</syntaxhighlight>
</pre>


Idea pratica:
Idea pratica:
Riga 180: Riga 180:


== Esempio dry run ==
== Esempio dry run ==
<syntaxhighlight lang="bash">
<pre>
pyinfra inventory.py deploy.py --dry
pyinfra inventory.py deploy.py --dry
</syntaxhighlight>
</pre>


Utile prima di un deploy reale.
Utile prima di un deploy reale.

Versione delle 18:55, 29 mar 2026

Esempi Pyinfra

Questa pagina raccoglie esempi leggibili e progressivi: si parte dal minimo indispensabile e si arriva a pattern piu vicini a un uso reale.

Prima idea da fissare

Un progetto pyinfra semplice ha di solito almeno due file:

inventory.py
deploy.py

L'inventory descrive i target. Il deploy descrive cosa fare.

Esempio base 1: esecuzione su host locali

Se vuoi solo capire la CLI:

pyinfra @local exec -- echo "hello world"

Questo serve quando vuoi verificare:

  • che pyinfra sia installato
  • che il runner funzioni
  • che l'output arrivi correttamente

Esempio base 2: inventory minimale

web_servers = [
    "web-01.example.net",
    "web-02.example.net",
]

Qui hai solo una lista di host.

Esempio base 3: operation semplice

from pyinfra.operations import server

server.shell(
    name="Show uptime",
    commands=["uptime"],
)

Esecuzione:

pyinfra inventory.py deploy.py

Esempio base 4: installare pacchetti

from pyinfra.operations import apt

apt.packages(
    name="Install packages",
    packages=["vim", "curl"],
    update=True,
)

Questo e un esempio di operation idempotente: se i pacchetti sono gia presenti, pyinfra non rifara cambiamenti inutili.

Esempio base 5: gestire file

from pyinfra.operations import files

files.file(
    name="Ensure app log exists",
    path="/var/log/app.log",
    user="app",
    group="app",
    mode="644",
)

Esempio base 6: gestire servizi

from pyinfra.operations import systemd

systemd.service(
    name="Ensure nginx is running",
    service="nginx",
    running=True,
    enabled=True,
)

Esempio intermedio 1: dati host

Inventory:

app_servers = [
    ("app-01.example.net", {"install_nginx": True}),
    ("app-02.example.net", {"install_nginx": False}),
]

Deploy:

from pyinfra import host
from pyinfra.operations import apt

if host.data.get("install_nginx"):
    apt.packages(
        name="Install nginx",
        packages=["nginx"],
        update=True,
    )

Qui usi Python per rendere il deploy diverso in base ai dati del target.

Esempio intermedio 2: gruppi

from pyinfra import host, local
from pyinfra.operations import server

if "web_servers" in host.groups:
    local.include("tasks/web.py")

if "db_servers" in host.groups:
    local.include("tasks/database.py")

server.shell(
    name="Run everywhere",
    commands=["hostname"],
)

Questo pattern e utile quando vuoi dividere la logica in file piu piccoli.

Esempio avanzato 1: deploy locale che richiama un helper Python

Questo e il pattern usato nel progetto Proxmox Web UI: pyinfra gira su @local ma esegue un helper esterno che contiene la logica vera.

#!/usr/bin/env python3
import os
import shlex
from pathlib import Path

from pyinfra.operations import server

BASE_DIR = Path(__file__).resolve().parents[1]
python_bin = os.environ.get("PYTHON_BIN", str(BASE_DIR / "venv" / "bin" / "python"))
helper = BASE_DIR / "lib" / "proxmox_ssh.py"
cmd = f"{shlex.quote(python_bin)} {shlex.quote(str(helper))}"

server.shell(
    name=f"Create Proxmox VM {os.environ.get('VM_NAME', '')}",
    commands=[cmd],
)

Idea pratica:

  • pyinfra fa da orchestratore locale
  • il file helper fa il lavoro specializzato
  • le variabili ambiente passano i parametri del job

Esempio avanzato 2: usare pyinfra come backend di una UI

Nel caso GazziNet il flusso e:

  1. la UI riceve input dell'utente
  2. la UI valida i campi
  3. la UI crea un job con stato e log
  4. il job lancia pyinfra @local deploy.py -y
  5. pyinfra richiama un helper che esegue SSH su Proxmox

Questa soluzione e utile quando vuoi:

  • separare presentazione e automazione
  • conservare log testuali chiari
  • evitare che il browser parli direttamente con Proxmox

Esempio avanzato 3: rete dinamica e validazione

Nel progetto VM automatiche la UI gestisce:

  • DHCP oppure IP statico
  • bridge selezionabile
  • VLAN opzionale
  • validazione preventiva bridge + VLAN
  • ricerca del primo VMID libero

In questo caso pyinfra non decide la rete da solo: riceve i valori gia normalizzati e li passa al backend di provisioning.

Esempio dry run

pyinfra inventory.py deploy.py --dry

Utile prima di un deploy reale.

Pattern reali da ricordare

  • tenere inventory e deploy in Git
  • separare logica generale e helper specializzati
  • validare input prima di lanciare pyinfra
  • non mescolare segreti nei file versionati
  • aggiungere sempre un modo semplice per verificare il risultato

Collegamenti