Skip to content

dnf Operations

Manage dnf packages and repositories. Note that dnf package names are case-sensitive.

Facts used in these operations: dnf.DnfDisabledModules, dnf.DnfEnabledModules, rpm.RpmPackageProvides, rpm.RpmPackages.

dnf.key

Stateless operation

This operation will always execute commands and is not idempotent.

Add dnf gpg keys with rpm.

dnf.key(src: 'str',
         **kwargs,
    )
  • key: filename or URL

Note: always returns one command, not idempotent

Example:

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 gpg key",
    src=f"https://download.docker.com/linux/{linux_id}/gpg",
)

Global arguments

This operation also inherits all global arguments.

dnf.module

Manage a dnf module (application stream).

dnf.module(module: 'str', stream: 'str | None' = None, enabled: 'bool' = True,
         **kwargs,
    )
  • module: name of the dnf module
  • stream: name of the stream, required when enabled=True, ignored when enabled=False
  • enabled: True (default) to enable the stream, False to disable the module

Application streams let you install multiple parallel versions of the same component. Only one stream of a module can be enabled at a time.

Stream switching: dnf module enable will refuse to switch streams when packages from the currently-active stream are installed. In that case, remove the installed packages (or dnf module reset) before switching.

Examples:

from pyinfra.operations import dnf

# Enable a stream
dnf.module(
    name="Enable PostgreSQL 16 module stream",
    module="postgresql",
    stream="16",
    _sudo=True,
)

# Disable a module (all streams become inactive)
dnf.module(
    name="Disable the ruby module",
    module="ruby",
    enabled=False,
    _sudo=True,
)

Global arguments

This operation also inherits all global arguments.

dnf.packages

Install/remove/update dnf packages & updates.

dnf.packages(
         packages: 'str | list[str] | None' = None,
         present=True,
         latest=False,
         update=False,
         clean=False,
         nobest=False,
         extra_install_args: 'str | None' = None,
         extra_uninstall_args: 'str | None' = None,
         **kwargs,
    )
  • packages: packages to ensure
  • present: whether the packages should be installed
  • latest: whether to upgrade packages without a specified version
  • update: run dnf update before installing packages
  • clean: run dnf clean before installing packages
  • nobest: add the no best option to install
  • extra_install_args: additional arguments to the dnf install command
  • extra_uninstall_args: additional arguments to the dnf uninstall command

Versions: Package versions can be pinned as follows: <pkg>=<version>

Examples:

# Update package list and install packages
dnf.packages(
    name='Install Vim and Vim enhanced',
    packages=["vim-enhanced", "vim"],
    update=True,
)

# Install the latest versions of packages (always check)
dnf.packages(
    name="Install latest Vim",
    packages=["vim"],
    latest=True,
)

Global arguments

This operation also inherits all global arguments.

dnf.repo

Add/remove/update dnf repositories.

dnf.repo(
         src: 'str',
         present=True,
         baseurl: 'str | None' = None,
         description: 'str | None' = None,
         enabled=True,
         gpgcheck=True,
         gpgkey: 'str | None' = None,
         **kwargs,
    )
  • src: URL or name for the .repo file
  • present: whether the .repo file should be present
  • baseurl: the baseurl of the repo (if name is not a URL)
  • description: optional verbose description
  • enabled: whether this repo is enabled
  • gpgcheck: whether set gpgcheck=1
  • gpgkey: the URL to the gpg key for this repo

Baseurl/description/gpgcheck/gpgkey: These are only valid when name is a filename (ie not a URL). This is for manual construction of repository files. Use a URL to download and install remote repository files.

Examples:

# Download a repository file
dnf.rpm(
    name="Install Docker-CE repo via URL",
    src="https://download.docker.com/linux/centos/docker-ce.repo",
)

# Create the repository file from baseurl/etc
dnf.repo(
    name="Add the Docker CentOS repo",
    src="DockerCE",
    baseurl="https://download.docker.com/linux/centos/7/$basearch/stable",
)

Global arguments

This operation also inherits all global arguments.

dnf.rpm

Add/remove .rpm file packages.

dnf.rpm(src: 'str', present=True,
         **kwargs,
    )
  • src: filename or URL of the .rpm package
  • present: whether ore not the package should exist on the system

URL sources with present=False: If the .rpm file isn't downloaded, pyinfra can't remove any existing package as the file won't exist until mid-deploy.

Example:

major_centos_version = host.get_fact(LinuxDistribution)["major"]
dnf.rpm(
   name="Install EPEL rpm to enable EPEL repo",
   src=f"https://dl.fedoraproject.org/pub/epel/epel-release-latest-{major_centos_version}.noarch.rpm",
)

Global arguments

This operation also inherits all global arguments.

dnf.update

Stateless operation

This operation will always execute commands and is not idempotent.

Updates all dnf packages.

dnf.update**kwargs,    )

Global arguments

This operation also inherits all global arguments.