Files
warewulf/userdocs/overlays/templates.rst
Jonathon Anderson 2bad789f4f Fix newline handling in file, softlink, and ImportLink template functions
Use state-based routing instead of sentinel strings, so whitespace-trimming
syntax (e.g. `{{- file "name" -}}`) correctly creates all named files and
symlinks.

Fixes: #2118

Signed-off-by: Jonathon Anderson <janderson@ciq.com>
Co-authored-by: Christian Goll <cgoll@suse.com>
Signed-off-by: Jonathon Anderson <janderson@ciq.com>
2026-04-17 22:51:10 -06:00

285 lines
7.5 KiB
ReStructuredText

.. _templates:
=========
Templates
=========
Templates (denoted in overlays with a ``.ww`` suffix) allow you to create
dynamic configuration specifically for the node that it is applied to. Templates
have access to all metadata from the node registry (``nodes.conf``) and much of
the server configuration (``warewulf.conf``), and can also reference and import
files from the server file system.
Warewulf uses the ``text/template`` engine to facilitate implementing dynamic
content. This template format is documented at `pkg.go.dev/text/template.
<https://pkg.go.dev/text/template>`_
.. note::
When the template is rendered within a built overlay image, the ``.ww`` will
be dropped, so ``/etc/hosts.ww`` will end up being ``/etc/hosts``.
Non-Overlay Templates
=====================
Most Warewulf templates are included in overlays, but there are a few
non-overlay templates as well.
* ``/etc/warewulf/ipxe/``: includes iPXE script templates to direct iPXE during
the network boot process.
* ``/etc/warewulf/grub/``: includes GRUB script templates to direct GRUB during
the network boot process.
* ``/usr/share/warewulf/bmc/``: includes templates to generate BMC control
commands for the ``wwctl power``, ``wwctl sensor``, and ``wwctl console``
commands.
Template documentation
======================
Templates can include documentation to be included in the output of ``wwctl overlay info``.
.. code::
{{/* wwdoc: Your documentation text */}}
Template variables
==================
Overlay templates have access to a number of variables that provide information
about the server configuration, the node being provisioned, and all nodes in the
cluster. An example of the variables available, and their use, is included with
Warewulf in the ``tstruct.ww`` template of the ``debug`` overlay.
Variables used in an overlay template can be documented by adding a comment to
the template with the form ``{{/* .My.Var: Your help text */}}``. Variable help
text defined in a comment replaces that variable's default help text in the
output of ``wwctl overlay info``.
Template functions
==================
Warewulf templates have access to a number of functions that assist in creating
more dynamic and expressive templates.
Default functions
-----------------
``text/template`` includes a number of `default functions
<https://pkg.go.dev/text/template#hdr-Functions>`_ that are available during
Warewulf template processing.
Sprig
-----
Supplementing the default functions, Warewulf templates also have access to
`Sprig functions.`_
.. _Sprig functions.: https://masterminds.github.io/sprig/
Include
-------
Reads content from the given file into the template. If the file does not begin
with ``/`` it is considered relative to ``Paths.Sysconfdir``.
.. code-block::
{{ Include "/root/.ssh/authorized_keys" }}
IncludeFrom
-----------
Reads content from the given file from the given image into the template.
.. code-block::
{{ IncludeFrom $.ImageName "/etc/passwd" }}
IncludeBlock
------------
Reads content from the given file into the template, stopping when the provided
abort string is found.
.. code-block::
{{ IncludeBlock "/etc/hosts" "# Do not edit after this line" }}
.. _importLink:
ImportLink
----------
Causes the processed template file to become a symlink to the same target as the
referenced symlink.
.. code-block::
{{- ImportLink "/etc/localtime" -}}
When paired with ``file``, ``ImportLink`` can create multiple symlinks from a
single template.
.. code-block::
{{- file "/tmp/test-link1" -}}
{{- softlink "/tmp/test-target1" -}}
{{- file "/tmp/test-link2" -}}
{{- softlink "/tmp/test-target2" -}}
basename
--------
Returns the base name of the given path.
.. code-block::
{{- range $type, $name := $.Tftp.IpxeBinaries }}
if option architecture-type = {{ $type }} {
filename "/warewulf/{{ basename $name }}";
}
{{- end }}
file
----
Write the content from the template to the specified file name. May be specified
more than once in a template to write content to multiple files.
When no ``file`` call is present, all template output is written to the
**default output path**: the template filename with the ``.ww`` suffix stripped
(e.g., ``/etc/hosts.ww````/etc/hosts``).
When one or more ``file`` calls are present, each call redirects subsequent
template output to that named file. Any content rendered before the first
``file`` call is not written to disk. A ``softlink`` or ``ImportLink`` placed
before any ``file`` call still applies to the default output path and is
written to disk even when named files are also present.
.. code-block::
{{- range $devname, $netdev := .NetDevs }}
{{- $filename := print "ifcfg-" $devname ".conf" }}
{{- file $filename -}}
{{/* content here */}}
{{- end }}
.. _softlink:
softlink
--------
Causes the processed template file to become a symlink to the referenced target.
.. code-block::
{{- printf "%s/%s" "/usr/share/zoneinfo" .Tags.localtime | softlink -}}
When paired with ``file``, ``softlink`` can create multiple symlinks from a
single template.
.. _readlink:
readlink
--------
Equivalent to ``filepath.EvalSymlinks``. Returns the target path of a named
symlink.
.. code-block::
{{ readlink /etc/localtime }}
IgnitionJson
------------
Generates JSON suitable for use by Ignition to create partitions and file
systems, from the data stored in a node's native ``disks`` and ``filesystems``
fields.
.. code-block::
{{ IgnitionJson }}
abort
-----
Immediately aborts processing the template and does not write a file.
.. code-block::
{{- abort -}}
nobackup
--------
Disables the creation of a backup file when replacing files with the current
template.
.. code-block::
{{- nobackup -}}
.. _UniqueField:
UniqueField
-----------
Returns a filtered version of a multi-line input string. Input is expected to be
a field-separated format with one record per line (terminated by ``\n``). Order of
lines is preserved, with the first matching line taking precedence.
For example, the following template snippet has been used in the ``syncuser`` overlay
to generate a combined ``/etc/passwd``.
.. code-block::
{{
printf "%s\n%s"
(IncludeFrom $.ImageName "/etc/passwd" | trim)
(Include (printf "%s/%s" .Paths.Sysconfdir "passwd") | trim)
| UniqueField ":" 0 | trim
}}
SystemdEscape
-------------
Escapes a string for use in a systemd unit file.
Escape rules are documented at `systemd.unit. <https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#String%20Escaping%20for%20Inclusion%20in%20Unit%20Names>`_
SystemdEscapePath
-----------------
Escapes a path for use in a systemd unit file.
.. code-block::
{{- file (print ($fs.path | SystemdEscapePath) ".mount") -}}
Escape rules are documented at `systemd.unit. <https://www.freedesktop.org/software/systemd/man/latest/systemd.unit.html#String%20Escaping%20for%20Inclusion%20in%20Unit%20Names>`_
Examples
========
Many example templates are included in the distribution overlays. The ``debug``
template also includes a ``tstruct.ww`` template that includes much of the
available metadata.
.. code-block:: shell
wwctl overlay show debug tstruct.ww
wwctl overlay show debug tstruct.ww --render=n1
Node-Specific Files
-------------------
Sometimes there is the need to have specific files for each cluster node which
can't be generated by a template (e.g., a per-node Kerberos keytab). You can
include these files with following template:
.. code-block::
{{ Include (printf "/srv/%s/%s" .Id "payload") }}