Skip to content

Commit

Permalink
libdnf5 "actions" plugin documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jrohel committed Jul 20, 2023
1 parent 6e63aa8 commit 3271406
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 0 deletions.
1 change: 1 addition & 0 deletions dnf5.spec
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ Libdnf5 plugin that allows to run actions (external executables) on hooks.

%files -n libdnf5-plugin-actions
%{_libdir}/libdnf5/plugins/actions.*
%{_mandir}/man8/libdnf5-actions.8.*
%endif


Expand Down
4 changes: 4 additions & 0 deletions doc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ if(WITH_MAN)
)
add_dependencies(doc doc-man)

if(WITH_PLUGIN_ACTIONS)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/libdnf5-actions.8 DESTINATION share/man/man8)
endif()

if(WITH_DNF5DAEMON_CLIENT)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/man/dnf5daemon-client.8 DESTINATION share/man/man8)
endif()
Expand Down
1 change: 1 addition & 0 deletions doc/conf.py.in
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ man_pages = [
('dnf5_plugins/builddep.8', 'dnf5-builddep', 'Builddep Command', AUTHORS, 8),
('dnf5_plugins/copr.8', 'dnf5-copr', 'Copr Command', AUTHORS, 8),
('dnf5_plugins/repoclosure.8', 'dnf5-repoclosure', 'Repoclosure Command', AUTHORS, 8),
('libdnf5_plugins/actions.8', 'libdnf5-actions', 'Actions plugin', AUTHORS, 8),
('misc/comps.7', 'dnf5-comps', 'Comps Groups And Environments', AUTHORS, 7),
('misc/filtering.7', 'dnf5-filtering', 'Packages Filtering', AUTHORS, 7),
('misc/installroot.7', 'dnf5-installroot', 'Installroot Parameter', AUTHORS, 7),
Expand Down
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Welcome to DNF5's documentation!
tutorial/index
tutorial/bindings/index
api/index
libdnf5_plugins/index
commands/index
dnf5_plugins/index
dnf5.8
Expand Down
180 changes: 180 additions & 0 deletions doc/libdnf5_plugins/actions.8.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
..
Copyright Contributors to the libdnf project.
This file is part of libdnf: https://github.com/rpm-software-management/libdnf/

Libdnf is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

Libdnf is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with libdnf. If not, see <https://www.gnu.org/licenses/>.

.. _actions_plugin_ref-label:

======================
libdnf5 Actions Plugin
======================

Description
===========

This plugin allows defining actions to be executed throught libdnf5 callbacks hooks.
Each action is hooked to one specific callback. Actions for ``pre_transaction`` and
``post_transaction`` callbacks may define a (glob-like) filtering rule on the package
NEVRA or package files, as well as whether the package is incoming or outgoing.


Configuration
=============

The plugin does not extend the standard configuration. However, it reads "actions" files.

The actions files are read from ``<libdnf5_plugins_config_dir>/actions.d/`` directory. Only files
with ".actions" extension are read.


Actions file format
===================

Empty lines and lines that start with a '#' character (comment line) are ignored.

Each non-comment line defines an action and consists of five items separated by colons: ``callback_name:package_filter:direction:reserved:command``.

``callback_name``

* ``pre_base_setup``
* ``post_base_setup``
* ``pre_transaction``
* ``post_transaction``

``package_filter``
A (glob-like) filtering rule aplied on the package NEVRA (also in the shortened forms) or package files.

Empty filter means executing the command once with no information about the package.
The "*" filter means executing the command for each package in the transaction that matches the ``direction`` filter.
The filter can be non-empty only for ``pre_transaction`` and ``post_transaction`` callbacks.

``direction``
Filters packages by their direction (coming into the system/going out of the system) in a transaction.
If empty, the filter is not applied.
The filter can only be non-empty when combined with a non-empty ``package_filter``.

* ``in`` - packages coming to the system (downgrade, install, reinstall, upgrade)
* ``out`` - packages going out of the system (upgraded, downgraded, reinstalled, removed, replaced/obsoleted)

``command``
Any executable file with arguments.

Arguments are separated by spaces. A space within an argument can be written using escaping.
Escaping can also be used to prevent substitution and to pass special characters \\a, \\b, \\f, \\n, \\r, \\t, \\v.
Unescaping of arguments is done after substitution.

The following variables in the command will be substituted:

* ``${pid}`` - process ID
* ``${conf.<option_name>}`` - option from base configuration
* ``${var.<variable_name>}`` - variable
* ``${tmp.<actions_plugin_variable_name>}`` - variable exists only in actions plugin context
* ``${pkg.<package_attribute_name>}`` - value of the package attribute

* ``${pkg.name}`` - package name
* ``${pkg.arch}`` - package arch
* ``${pkg.version}`` - package version
* ``${pkg.release}`` - package release
* ``${pkg.epoch}`` - package epoch
* ``${pkg.na}`` - package name.architecture
* ``${pkg.evr}`` - package epoch-version-release
* ``${pkg.nevra}`` - package nevra (0 epoch is hidden)
* ``${pkg.full_nevra}`` - package full nevra (epoch is always present) ${name}-${epoch}:${ver}-${rel}.${arch}
* ``${pkg.repo_id}`` - package repository id
* ``${pkg.license}`` - package license
* ``${pkg.location}`` - the change of package state in the transaction:
* ``${pkg.vendor}`` - package vendor
* ``${pkg.action}`` - action performed on the package:

* I - newly installed package
* U - package installed as an upgrade
* D - package installed as an downgrade
* R - package used for reinstallation
* E - erased (removed) package from the system (was upgraded/downgraded/reinstalled/removed)
* O - replaced (obsoleted) package

The command will be evaluated for each package that matched the ``package_filter`` and
the ``direction``. However, after variable substitution, any duplicate commands will be
removed and each command will only be executed once per transaction.
The commands are executed in sequence. There is no parallelism. Argument substitution is performed
after the previous command has completed. This allows the substitution to use the results of the previous commands.
The order of execution of the commands follows the order in the action files, but may differ from the order of
packages in the transaction. In other words, when you define several action lines for the same
``package_filter`` and ``direction`` these lines will be executed in the order they were defined in the action
file when the ``package_filter`` and ``direction`` matches a package. However, the order
of when a particular ``package_filter`` is invoked depends on the position
of the corresponding package in the transaction.

``reserved``
Reserved for future use. Now empty.


Action standard output format
=============================

The standard output of each executed action (command) is captured and processed.
Each line of output can set the value or unset one actions plugin variable. It can also
change the value of an option from the base configuration or a variable.

Output line format
------------------
* tmp.<actions_plugin_variable_name>=<value> - sets the value of action plugins variable <actions_plugin_variable_name>
* tmp.<actions_plugin_variable_name> - removes the action plugins variable if it exists
* conf.<option_name>=<value> - sets the value of option <option_name> in the base configuration
* var.<variable_name>=<value> - sets value of the vatiable <variable_name>


An example actions file:
========================
.. code-block:: none
# Prints header with process id
pre_base_setup::::/usr/bin/sh -c echo\ -------------------------------------\ >>/tmp/actions-trans.log
pre_base_setup::::/usr/bin/sh -c date\ >>/tmp/actions-trans.log
pre_base_setup::::/usr/bin/sh -c echo\ libdnf5\ pre_base_setup\ was\ called.\ Process\ ID\ =\ '${pid}'.\ >>/tmp/actions-trans.log
# Prints the value of the configuration option "defaultyes".
pre_base_setup::::/bin/sh -c echo\ 'pre_base_setup:\ conf.defaultyes=${{conf.defaultyes}}'\ >>\ {context.dnf.installroot}/actions.log
# Prints a message that the "post_base_setup" callback was called.
post_base_setup::::/usr/bin/sh -c echo\ libdnf5\ post_base_setup\ was\ called.\ >>/tmp/actions-trans.log
# Prints the information about the start of the transaction.
# Since package_filter is empty, it executes the commands once.
pre_transaction::::/usr/bin/sh -c echo\ Transaction\ start.\ Packages\ in\ transaction:\ >>/tmp/actions-trans.log
# Logs all packages (package action, full_nevra, repo id) in transaction into a file.
# Uses the shell command "echo" and redirection to a file.
pre_transaction:*:::/usr/bin/sh -c echo\ '${pkg.action}'\ '${pkg.full_nevra}'\ '${pkg.repo_id}'\ >>/tmp/actions-trans.log
# Prints the date and time and information about the end of the transaction.
# Since package_filter is empty, it executes the commands once.
post_transaction::::/usr/bin/sh -c date\ >>/tmp/actions-trans.log
post_transaction::::/usr/bin/sh -c echo\ Transaction\ end.\ Repositories\ used\ in\ the\ transaction:\ >>/tmp/actions-trans.log
# Logs all the repositories from which packages were used in the transaction to install on the system.
# Each repository will be listed only once, even if multiple packages from the same repository were used.
# The same command (after variables substitution) is executed only once per transaction.
post_transaction:*:in::/usr/bin/sh -c echo\ '${pkg.repo_id}'\ >>/tmp/actions-trans.log
# ==============================================================================================
# The next two actions emulate the DNF4 snapper plugin. It uses the "snapper" command-line proram.
# Creates pre snapshot before the transaction and stores the snapshot number in the "tmp.snapper_pre_number" variable.
pre_transaction::::/usr/bin/sh -c echo\ "tmp.snapper_pre_number=$(snapper\ create\ -t\ pre\ -p)"
# If the variable "tmp.snapper_pre_number" exists, it creates post snapshot after the transaction and removes the variable "tmp.snapper_pre_number".
post_transaction::::/usr/bin/sh -c [\ -n\ "${tmp.snapper_pre_number}"\ ]\ &&\ snapper\ create\ -t\ post\ --pre-number\ "${tmp.snapper_pre_number}"\ ;\ echo\ tmp.snapper_pre_number
11 changes: 11 additions & 0 deletions doc/libdnf5_plugins/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
===============
libdnf5 Plugins
===============


.. toctree::
:maxdepth: 1

actions.8

..

0 comments on commit 3271406

Please sign in to comment.