holo-files - Holo plugin to provision files
When using Holo, configuration is usually stored in system packages, so files can be provisioned by just including them in a configuration package. This plugin extends this basic capability to allow one package (a configuration package) to overwrite or modify a file that has been installed by another package (an application package).
Configuration packages that want to use this plugin must place files in the resource directory at
/usr/share/holo/files. Each resource file works on a certain target, as determined by its file name:
/usr/share/holo/files/20-webserver/etc/nginx/nginx.conf \__________/\___________________/ | | | `-- path to target | `-- disambiguator
The disambiguator is always required, and allows multiple resource files to operate on the same target (sorted alphabetically by their disambiguator). The pattern of putting a number at the start of the disambiguator is not required, but useful to control the ordering of resource files.
Each target file that has such resource files is an entity within Holo. Its entity ID is
$target is the absolute path to the target file.
Resource files are applied on the target base, the initial version of the target file that was found during the first
holo apply run. This target base is saved at
Resource files that are plain files or symlinks will just overwrite the target base (or all previous entries), whereas executable resource files with an extra
.holoscript suffix can be used to modify the target base (or the result of a previous application step). The target contents will be piped through the script. This is typically used when the default configuration for an application shall be used, but with some minor modifications. The following example uses the default configuration for pacman(8), but enables the "Color" and "TotalDownload" options:
$ cat /usr/share/holo/files/20-enable-color/etc/pacman.conf.holoscript #!/bin/sh sed 's/^#\s*Color$/Color/; s/^#\s*TotalDownload$/TotalDownload/' $ sudo holo apply file:/etc/pacman.conf Working on file:/etc/pacman.conf store at /var/lib/holo/files/base/etc/pacman.conf passthru /usr/share/holo/files/20-enable-color/etc/pacman.conf.holoscript
When writing the new target file, ownership and permissions will be copied from the target base, and thus from the original target file. Furthermore, a copy of the provisioned target file is written to
/var/lib/holo/files/provisioned/$target for use by
holo diff file:$target.
In normal operation, holo-files will refuse to operate on a target file that has been modified or deleted by the user or by another program. Apply
--force to reset the target file to its defined state.
Each target file is originally installed by an application package. When that application package is upgraded, system package managers usually detect that the file has been modified, and store the new version contained in the application package next to the target file, in paths such as
$target.rpmnew # for RPM (Fedora, Mageia, openSUSE etc.) $target.dpkg-dist # for dpkg (Debian, Ubuntu etc.) $target.pacnew # for pacman (Arch Linux etc.) $target.apk-new # for APK (Alpine Linux etc.)
When this happens, the next
holo apply run will detect this file and update its target base with this file:
$ sudo pacman -Syu ... installing pacman ... warning: /etc/pacman.conf installed as /etc/pacman.conf.pacnew ... $ sudo holo apply file:/etc/pacman.conf Working on file:/etc/pacman.conf store at /var/lib/holo/files/base/etc/pacman.conf passthru /usr/share/holo/files/20-enable-color/etc/pacman.conf.holoscript >> found updated target base: /etc/pacman.conf.pacnew -> /var/lib/holo/files/base/etc/pacman.conf
(Unless disabled, it would not normally be nescessary to manually run
sudo holo apply in the above example, as holo-files provides a pacman hook that causes pacman to automatically call
holo apply to handle
.pacnew files. This is not (yet) true for other package managers.)
This means that when configuration is applied as a holoscript on top of the default configuration, future updates to the default configuration will automatically be picked up, as long as
holo apply is run after the system update.
When detecting these files, to know which suffixes to look for, holo-files inspects
ID_LIKE in os-release(5) to determine which family the operating system belongs to, and thus which package manager is used. It currently recognizes
If there exist target bases below
/var/lib/holo/files for which there are no corresponding resource files below
/usr/share/holo/files, these target bases are considered orphaned.
This usually occurs because a package has been removed from the system, or because a different package version were installed that do not contain the resource files in question anymore.
There are two subcases to consider, if only configuration packages were deleted,
holo apply will restore the target base (as installed by the application package):
Scrubbing file:/etc/resourcefile-deleted.conf (all repository files were deleted) restore /var/lib/holo/files/base/etc/resourcefile-deleted.conf
If the application package (to whom the target file belongs) has also been deleted, the target base will be deleted instead of restored:
Scrubbing file:/etc/targetfile-deleted.conf (target was deleted) delete /var/lib/holo/files/base/etc/targetfile-deleted.conf
This algorithm ensures that after any number of package installation and removal operations, a single
holo apply will converge all old and new target files to the desired state.
holo apply will refuse to work on target files that have been modified by the user or another program, unless
--force is given:
$ sudo rm /etc/pacman.conf $ sudo vim /etc/ssh/sshd_config ... $ sudo holo apply Working on file:/etc/pacman.conf store at /var/lib/holo/files/base/etc/pacman.conf apply /usr/share/holo/files/01-base/etc/pacman.conf !! skipping target: file has been deleted by user (use --force to restore) Working on file:/etc/ssh/sshd_config store at /var/lib/holo/files/base/etc/ssh/sshd_config apply /usr/share/holo/files/10-openssh/etc/ssh/sshd_config !! skipping target: file has been modified by user (use --force to restore)
holo diff command can be used to produce a diff between the last provisioned and the current state of the target files.
holo apply --force can be used to reset the target files to their defined state.
holo(8) provides the user interface for using this plugin.
Further documentation is available at the project homepage: https://holocm.org
Please report any issues and feature requests at GitHub: https://github.com/holocm/holo/issues