.. -*- mode: rst -*-
.. vim: ft=rst
.. _server-plugins-structures-bundler:
=======
Bundler
=======
Bundler is used to describe groups of inter-dependent configuration
entries, such as the combination of packages, configuration files,
and service activations that comprise typical Unix daemons. Bundles are
used to add groups of configuration entries to the inventory of client
configurations, as opposed to describing particular versions of those
entries. For example, a bundle could say that the configuration file
``/etc/passwd`` should be included in a configuration, but will not
describe the particular version of ``/etc/passwd`` that a given client
will receive.
Group and Client tags can be used inside of bundles to differentiate
which entries particular clients will recieve; this is useful for the
case where entries are named differently across systems; for example,
one Linux distro may have a package called ``openssh`` while another
uses the name ``ssh``. See :ref:`xml-group-client-tags` for details
and a longer example.
A brief example:
.. code-block:: xml
Note that we do not specify *how* a given entry should be managed,
only that it should be. The concrete specification of each entry will
be provided by a different plugin such as
:ref:`server-plugins-generators-cfg`,
:ref:`server-plugins-generators-rules`, or
:ref:`server-plugins-generators-packages`.
Alternatively, you can use fully-bound entries in Bundler, which has
various uses. For instance:
.. code-block:: xml
In this example, both Service tags and one Package tag are fully bound
-- i.e., all information required by the client to manage those
entries is provided in the bundle itself.
.. _server-plugins-structures-bundler-magic:
Bundle "Magic"
==============
Bundles are collections of *related* entries. That point is very,
very important, because a bundle performs certain "magic" actions when
one or more entries in it are modified:
* :xml:type:`Service ` entries whose ``restart``
attribute is ``true`` (the default) will be restarted.
* :xml:type:`Action ` entries whose ``when`` attribute is
``modified`` will be run.
Because of these two magic actions, it's extremely important to
structure your bundles around Service and Action entries, rather than
around some loose idea of which entries are related. For instance, in
order to manage a Bcfg2 server, a number of packages, paths, services,
etc. must be managed. But not all of these entries would require
``bcfg2-server`` to be restarted, so to limit restarts it's wise to
split these entries into two bundles. See
:ref:`server-plugins-structures-bundler-bcfg2-server` for an example
of this.
.. _server-plugins-structures-bundler-index-disabling-magic:
Disabling Magic
---------------
Disabling magic bundler actions can be done in one of two ways:
* On a per-entry basis. Set ``restart="false"`` on a Service to
prevent it from being restarted when the bundle is modified. Set
``when="always"`` on an Action to cause it to run every time,
regardless of whether or not the bundle was modified.
* On a per-bundle basis. Set ``independent="true"`` on the top-level
``Bundle`` tag to signify that the bundle is a collection of
independent (i.e., unrelated) entries, and to prevent any magic
actions from being performed. (This is similar to the ``Base``
plugin in older versions of Bcfg2.) This was added in Bcfg2 1.4.
Service entries in independent bundles are never restarted, and Action
entries in independent bundles are only executed if ``when="always"``.
(I.e., an Action entry in an independent bundle with
``when="modified"`` is useless.)
.. _server-plugins-structures-bundler-index-genshi-templates:
Genshi templates
================
Genshi XML templates allow you to use the `Genshi
`_ templating system to dynamically
generate a bundle. Genshi templates can be specified one of two ways:
1. Add an XML-style genshi template to the Bundler directory with a
``.genshi`` and the associated namespace attribute. *This is
deprecated as of Bcfg2 1.4.*
2. Add the Genshi namespace to your existing XML
bundle.
See :ref:`xml-genshi-templating` for details.
Troubleshooting
---------------
To render a bundle for a given client, you can run::
bcfg2-info buildbundle
This will render the template; it will not fully bind all of the
entries in the bundle.
See :ref:`bcfg2-info ` for more details.
.. _server-plugins-structures-bundler-index-dependencies:
Dependencies
============
Dependencies on other bundles can be specified by adding an empty
bundle tag that adds another bundle by name, e.g.:
.. code-block:: xml
...
The dependent bundle is added to the list of bundles sent to the
client, *not* to the parent bundle itself. In other words, if an
entry in the dependent bundle changes, Services are restarted and
Actions are run in the dependent bundle *only*. An example:
``nfs-client.xml``:
.. code-block:: xml
``automount.xml``:
.. code-block:: xml
If a new ``nfs-utils`` package was installed, the ``nfslock``,
``rpcbind``, and ``nfs`` services would be restarted, but *not* the
``autofs`` service. Similarly, if a new ``/etc/auto.misc`` file was
sent out, the ``autofs`` service would be restarted, but the
``nfslock``, ``rpcbind``, and ``nfs`` services would not be restarted.
Altsrc
======
.. toctree::
:maxdepth: 1
../altsrc
Examples
========
In some cases, configuration files need to include the client's hostname
in their name. The following template produces such a config file entry.
.. code-block:: xml
Depending on the circumstance, these configuration files can either be
handled by individual entries in :ref:`server-plugins-generators-cfg`,
or can be mapped to a single entry by using the
:ref:`server-plugins-structures-altsrc` feature.
In this example, configuration file names are built using probed results
from the client. getmac is a probe that gathers client MAC addresses
and returns them in a newline delimited string.
.. code-block:: xml
.. note::
* The use of the altsrc directive causes all ifcfg files to be
handled by the same plugin and entry.
* The blocks have only been available in genshi since
0.4 (http://genshi.edgewall.org/ticket/84)
If you want a file to be only on a per-client basis, you can use an
if declaration.
.. code-block:: xml
or alternately
.. code-block:: xml
or yet another way
.. code-block:: xml
The final form is preferred if there is no code inside the block that
would fail on other clients.
While these examples are simple, the test in the if block can in fact
be any python statement.
.. _server-plugins-structures-bundler-index-examples:
Other examples
==============
Some simple examples of Bundles can be found in the `Bcfg2 example repository`_.
.. _Bcfg2 example repository: https://github.com/solj/bcfg2-repo
In addition to the example repository, the following is a list of some
more complex example Bundles.
.. toctree::
:maxdepth: 1
bcfg2
kernel
moab
nagios
ntp
snmpd
torque
yp