Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ pyinfra @local ...
pyinfra my-server.net,@local ...

# Execute against a Docker container
pyinfra @docker/centos:8 ...
pyinfra @docker/fedora:43 ...
```

### Limit
Expand Down Expand Up @@ -132,7 +132,7 @@ For example, here we ensure that `nginx` is installed on the remote servers:
# Ubuntu example
pyinfra inventory.py apt.packages nginx update=true _sudo=true

# Centos example
# Fedora example
pyinfra inventory2.py yum.packages nginx _sudo=true
```

Expand Down
5 changes: 2 additions & 3 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ To debug pyinfra within PyCharm, you need to [explicitly enable support for Geve
pyinfra aims to be compatible with all Unix-like operating systems and is currently developed against:

+ Linux distros:
* Ubuntu 18/20
* Ubuntu 20/22/24
* Debian 9/10
* CentOS 7/8
* Fedora 33
* Fedora 43
* Alpine 3.8
+ BSD flavours:
* OpenBSD 6
Expand Down
4 changes: 4 additions & 0 deletions docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ The currently executing host can be fetched from the ``host`` context variable.
# Get the actual current hostname from the host
from pyinfra.facts.server import Hostname
hostname = host.get_fact(Hostname)
print(f"hostname:{hostname}")

How do I use sudo in an operation?
----------------------------------
Expand All @@ -28,6 +29,7 @@ Sudo is controlled by one of the `privilege and user escalation arguments <argum

.. code:: python

from pyinfra.operations import apt
apt.packages(
packages=["iftop"],
_sudo=True,
Expand All @@ -43,6 +45,7 @@ Use the LINK ``files.file``, ``files.directory`` or ``files.link`` operations to

.. code:: python

from pyinfra.operations import files
files.file(
path="/etc/default/elasticsearch",
user="pyinfra",
Expand All @@ -57,6 +60,7 @@ Use the `retry behavior arguments <arguments.html#retry-behavior>`_ to automatic

.. code:: python

from pyinfra.operations import server
# Retry a network operation up to 3 times
server.shell(
name="Download file with retries",
Expand Down
22 changes: 18 additions & 4 deletions docs/getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ You can start pyinfra immediately with some ad-hoc command execution. The CLI al
# Execute over SSH
pyinfra my-server.net exec -- echo "hello world"

# Execute over SSH with options
pyinfra localhost --ssh-port 2222 --ssh-user vagrant exec -- echo "hello world"

# Execute within a new docker container
pyinfra @docker/ubuntu:18.04 exec -- echo "hello world"
pyinfra @docker/ubuntu:22.04 exec -- echo "hello world"

# Execute on the local machine (MacOS/Linux only - for now)
pyinfra @local exec -- echo "hello world"
Expand Down Expand Up @@ -66,8 +69,19 @@ To get started create an ``inventory.py`` containing our hosts to target:

.. code:: python

# Define a group as a list of hosts
my_hosts = ["my-server.net", "@docker/ubuntu:18.04"]
# Define a group as a list of hosts
my_hosts = [
# vagrant instance
("ubuntu2204", {
"ssh_port": 2222,
"ssh_hostname": "localhost",
"ssh_user": "vagrant",
"_sudo": True
}),
"my-server.net",
"@docker/ubuntu:22.04"
]


Now create a ``deploy.py`` containing our operations to execute:

Expand All @@ -79,7 +93,7 @@ Now create a ``deploy.py`` containing our operations to execute:
apt.packages(
name="Ensure the vim apt package is installed",
packages=["vim"],
_sudo=True, # use sudo when installing the packages
update=True,
)

This can now be executed like this:
Expand Down
48 changes: 38 additions & 10 deletions docs/using-operations.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ For example, these two operations will ensure that user ``pyinfra`` exists with
user="pyinfra",
group="pyinfra",
mode="644",
_sudo=True,
)


Expand Down Expand Up @@ -127,20 +126,38 @@ Adding data to inventories is covered in detail here: :doc:`inventory-data`. Dat
Host Facts
~~~~~~~~~~

Facts allow you to use information about the target host to control and configure operations. A good example is switching between ``apt`` & ``yum`` depending on the Linux distribution. Facts are imported from ``pyinfra.facts.*`` and can be retrieved using the ``host.get_fact`` function:
Facts allow you to use information about the target host to control and configure operations. A good example is switching between ``apt`` & ``yum`` depending on the Linux distribution. You can get a fact like this:

.. code:: bash

pyinfra inventory.py fact server.LinuxName

Facts are imported from ``pyinfra.facts.*`` and can be retrieved using the ``host.get_fact`` function. If you save this in a file called `nano.py`:

.. code:: python

from pyinfra import host
from pyinfra.facts.server import LinuxName
from pyinfra.operations import yum
from pyinfra.operations import yum, apt

if host.get_fact(LinuxName) == "CentOS":
if host.get_fact(LinuxName) == "Fedora":
yum.packages(
name="Install nano via yum",
packages=["nano"],
_sudo=True
)
if host.get_fact(LinuxName) == "Ubuntu":
apt.packages(
name="Install nano via apt",
packages=["nano"],
update=True,
_sudo=True
)

.. code:: bash

pyinfra inventory.py nano.py


See :doc:`facts` for a full list of available facts and arguments.

Expand Down Expand Up @@ -322,24 +339,35 @@ Like ``host`` and ``inventory``, ``config`` can be used to set global defaults f
Enforcing Requirements
~~~~~~~~~~~~~~~~~~~~~~

The config object can be used to enforce a pyinfra version or Python package requirements. This can either be defined as a requirements text file path or simply a list of requirements:
The config object can be used to enforce a pyinfra version or Python package requirements. This can either be defined as a requirements text file path or simply a list of requirements. For example, if you create a `requirements.py` file with:

.. code:: python

# Require a certain pyinfra version
config.REQUIRE_PYINFRA_VERSION = "~=1.1"
config.REQUIRE_PYINFRA_VERSION = "~=3.0"

# Require certain packages
config.REQUIRE_PACKAGES = "requirements.txt" # path relative to the current working directory
config.REQUIRE_PACKAGES = "requirements.txt" # path is relative to the current working directory
config.REQUIRE_PACKAGES = [
"pyinfra~=1.1",
"pyinfra-docker~=1.0",
"pyinfra~=3.0",
]

And create a `requirements.txt` file with something like this:

.. code:: bash

pyinfra

Then modify the `nano.py` above to include these lines:
.. code:: python

from pyinfra import local
local.include("requirements.py")


Examples
--------

A great way to learn more about writing pyinfra deploys is to see some in action. There's a number of resources for this:
A great way to learn more about writing pyinfra deploys is to see some in action. Check out:

- `the pyinfra examples repository on GitHub <https://github.com/pyinfra-dev/pyinfra-examples>`_
12 changes: 0 additions & 12 deletions pyinfra-metadata.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,6 @@ path = "src/pyinfra/facts/brew.py"
type = "fact"
tags = ["package-manager", "system"]

[pyinfra.plugins."choco-ops"]
name = "choco"
path = "src/pyinfra/operations/choco.py"
type = "operation"
tags = ["package-manager", "system"]

[pyinfra.plugins."choco-facts"]
name = "choco"
path = "src/pyinfra/facts/choco.py"
type = "fact"
tags = ["package-manager", "system"]

[pyinfra.plugins."dnf-ops"]
name = "dnf"
path = "src/pyinfra/operations/dnf.py"
Expand Down
47 changes: 0 additions & 47 deletions src/pyinfra/facts/choco.py

This file was deleted.

3 changes: 2 additions & 1 deletion src/pyinfra/operations/apk.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
Manage apk packages.
Manage apk packages. (Alpine Linux)
"""

from __future__ import annotations
Expand Down Expand Up @@ -64,6 +64,7 @@ def packages(

.. code:: python

from pyinfra.operations import apk
# Update package list and install packages
apk.packages(
name="Install Asterisk and Vim",
Expand Down
1 change: 1 addition & 0 deletions src/pyinfra/operations/apt.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def key(src: str | None = None, keyserver: str | None = None, keyid: str | list[

.. code:: python

from pyinfra.operations import apt
# Note: If using URL, wget is assumed to be installed.
apt.key(
name="Add the Docker apt gpg key",
Expand Down
1 change: 1 addition & 0 deletions src/pyinfra/operations/brew.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ def packages(

.. code:: python

from pyinfra.operations import brew
# Update package list and install packages
brew.packages(
name='Install Vim and vimpager',
Expand Down
61 changes: 0 additions & 61 deletions src/pyinfra/operations/choco.py

This file was deleted.

1 change: 1 addition & 0 deletions src/pyinfra/operations/crontab.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ def crontab(

.. code:: python

from pyinfra.operations import crontab
# simple example for a crontab
crontab.crontab(
name="Backup /etc weekly",
Expand Down
5 changes: 4 additions & 1 deletion src/pyinfra/operations/dnf.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@ def key(src: str):

.. code:: python

from pyinfra import host
from pyinfra.operations import dnf
from pyinfra.facts.server import LinuxDistribution
linux_id = host.get_fact(LinuxDistribution)["release_meta"].get("ID")
dnf.key(
name="Add the Docker CentOS gpg key",
name="Add the Docker gpg key",
src=f"https://download.docker.com/linux/{linux_id}/gpg",
)

Expand Down
1 change: 1 addition & 0 deletions src/pyinfra/operations/docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def container(

.. code:: python

from pyinfra.operations import docker
# Run a container
docker.container(
name="Deploy Nginx container",
Expand Down
Loading