.. -*- mode: rst -*- .. _server-plugins-connectors-properties: ========== Properties ========== The Properties plugin is a connector plugin that adds information from XML, JSON, and YAML files into client metadata instances. Enabling Properties =================== First, ``mkdir /var/lib/bcfg2/Properties``. Each property file goes in this directory. Each will automatically be cached by the server, and reread/reparsed upon changes. Add **Properties** to your ``plugins`` line in ``/etc/bcfg2.conf``. Data Structures =============== Properties adds a new dictionary to client metadata instances that maps property file names to PropertyFile instances. A property file can be one of three types: * If the filename ends with ``.xml``, it will be parsed as XML and handled by :class:`Bcfg2.Server.Plugins.Properties.XMLPropertyFile`. See `XML Property Files`_ below. * If the filename ends with ``.json`` and JSON libraries are installed (either ``json`` or ``simplejson``, although ``json`` is highly recommended), it will be parsed as `JSON `_ and handled by :class:`Bcfg2.Server.Plugins.Properties.JSONPropertyFile`. See `JSON Property Files`_ below. * If the filename ends with ``.yaml`` or ``.yml`` and PyYAML is installed, it will be parsed as `YAML `_ and handled by :class:`Bcfg2.Server.Plugins.Properties.YAMLPropertyFile`. See `YAML Property Files`_ below. The XML interface is undoubtably the most powerful, as it natively supports schemas to check the data validity, client- and group-specific data, and data encryption. Usage ===== Common Interface ---------------- Different data types have different interfaces, but there are some usage patterns common to all properties files. Specific property files can be referred to in templates as ``metadata.Properties[]``. The data in property files is accessible via different attributes: +-----------+----------------+ | Data Type | Data Attribute | +===========+================+ | XML | ``xdata`` | +-----------+----------------+ | JSON | ``json`` | +-----------+----------------+ | YAML | ``yaml`` | +-----------+----------------+ For instance, in a :ref:`Genshi template `, you might do:: {% for item in metadata.Properties['foo.json'].json %}\ ${item} {% end %}\ {% for key, value in metadata.Properties['foo.yml'].yaml %}\ ${key} = ${value} {% end %}\ {% for el in metadata.Properties['foo.xml'].xdata.findall("Tag") %}\ ${el.get("name")} = ${el.text} {% end %}\ The raw contents of a properties file as a string are available via the ``data`` attribute, e.g., ``metadata.Properties['prop-file'].data``. .. _server-plugins-connectors-properties-write-back: Writing to Properties files ~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. versionadded:: 1.2.0 If you need to make persistent changes to properties data, you can use the ``write`` method of the :class:`Bcfg2.Server.Plugins.Properties.PropertyFile` class:: {% python import lxml.etree from genshi.template import TemplateError lxml.etree.SubElement(metadata.Properties['foo.xml'], "Client", name=metadata.hostname) if not metadata.Properties['foo.xml'].write(): raise TemplateError("Failed to write changes back to foo.xml") The interface is the same for YAML or JSON data. If writing XML data, the ``write`` method checks the data in the object against its schema before writing it; see `Data Structures`_ for details. Note that use of the ``write`` method can cause race conditions if you run more than one Bcfg2 server. If you run more than one Bcfg2 server, you can disable Properties write-back by setting the following in ``bcfg2.conf``:: [properties] writes_enabled = false .. _server-plugins-connectors-properties-xml: XML Property Files ------------------ The data in an XML property file can be accessed with the ``xdata`` attribute, an :class:`lxml.etree._Element` object documented `here `_. In addition to the ``xdata`` attribute that can be used to access the raw data, the following access methods are defined: * ``Match()`` parses the Group and Client tags in the file and returns a list of elements that apply to the client described by a set of metadata. For instance:: {% python ntp_servers = [el.text for el in metadata.Properties['ntp.xml'].Match(metadata) if el.tag == "Server"] %} * ``XMLMatch()`` parses the Group and Client tags in the file and returns an XML document containing only the data that applies to the client described by a set of metadata. (The Group and Client tags themselves are also removed, leaving only the tags and data contained in them.) For instance:: {% python ntp_servers = [el.text for el in metadata.Properties['ntp.xml'].XMLMatch(metadata).findall("//Server")] %} ``XMLMatch()`` can be run automatically on properties files by using the :ref:`server-plugins-connectors-properties-automatch` feature. You can also access the XML data that comprises a property file directly in one of several ways: * ``metadata.Properties['prop-file'].xdata`` is an lxml.etree._Element object representing the top-level element in the file. * ``metadata.Properties['prop-file'].data`` is the raw contents of the property file as a string. * ``metadata.Properties['prop-file'].entries`` is a list of lxml.etree._Element objects representing the direct children of the top-level element. (I.e., everything directly under the ```` tag.) The XML data in a property file is arbitrary, but a matching ``.xsd`` file can be created to assign a schema to a property file, which will be checked when running ``bcfg2-lint``. For instance, given:: Properties/dns-config.xml Properties/dns-config.xsd ``dns-config.xml`` will be validated against ``dns-config.xsd``. Although Properties files are technically freeform XML, the top-level XML tag should be ````. JSON Property Files ------------------- .. versionadded:: 1.3.0 The data in a JSON property file can be accessed with the ``json`` attribute, which is the loaded JSON data. The JSON properties interface does not provide any additional functionality beyond the `Common Interface`_. YAML Property Files ------------------- .. versionadded:: 1.3.0 The data in a YAML property file can be accessed with the ``yaml`` attribute, which is the loaded YAML data. Only a single YAML document may be included in a file. The YAML properties interface does not provide any additional functionality beyond the `Common Interface`_. .. _server-plugins-connectors-properties-automatch: Automatch ========= .. versionadded:: 1.3.0 You can enable :func:`Bcfg2.Server.Plugin.helpers.StructFile.XMLMatch()` for all XML Property files by setting ``automatch`` to ``true`` in the ``[properties]`` section of ``bcfg2.conf``. This makes ``metadata.Properties`` values :class:`lxml.etree._Element` objects that contain only matching data. (This makes it impossible to do :ref:`server-plugins-connectors-properties-write-back` as a side-effect.) In Python terms, setting ``automatch=true`` is the same as doing the following at the top of each template:: {% python for prop in metadata.Properties.values(): prop = prop.XMLMatch(metadata) %} The example above that describes ``XMLMatch()`` would then become simply:: {% python ntp_servers = [el.text for el in metadata.Properties['ntp.xml'].findall("//Server")] %} You can also enable automatch for individual Property files by setting the attribute ``automatch="true"`` on the top-level ```` tag. Conversely, if automatch is enabled by default in ``bcfg2.conf``, you can disable it for an individual Property file by setting ``automatch="false"`` on the top-level ```` tag. If you want to see what ``XMLMatch()``/automatch would produce for a given client on a given Properties file, you can use :ref:`bcfg2-info `:: bcfg2-info automatch props.xml foo.example.com If automatch is not enabled, you can force ``bcfg2-info`` to perform it anyway with ``-f``:: bcfg2-info automatch -f props.xml foo.example.com .. note:: Be sure to notice that enabling automatch changes the type of the data in ``metadata.Properties``; with automatch disabled, the values of the ``metadata.Properties`` dict are :class:`Bcfg2.Server.Plugins.Properties.PropertyFile` objects. With automatch enabled, they are :class:`lxml.etree._Element` objects. .. _server-plugins-connectors-properties-encryption: Encrypted Properties data ========================= .. versionadded:: 1.3.0 You can encrypt selected data in XML Properties files to protect that data from other people who need access to the repository. The data is decrypted transparently on-the-fly by the server; you never need to decrypt the data in your templates. Encryption is only supported on XML properties files. See :ref:`server-encryption` for details on encryption in general, and :ref:`xml-encryption` for details on encryption in XML files. Accessing Properties contents from Genshi Templates =================================================== Access contents of ``Properties/auth.xml``:: ${metadata.Properties['auth.xml'].xdata.find('file').find('bcfg2.key').text} Configuration ============= ``bcfg2.conf`` contains several miscellaneous configuration options for the Properties plugin, which can be set in the ``[properties]`` section. Any booleans in the config file accept the values "1", "yes", "true", and "on" for True, and "0", "no", "false", and "off" for False. It understands the following directives: * ``automatch``: Enable :ref:`server-plugins-connectors-properties-automatch`. Default is false. * ``writes_enabled``: Enable :ref:`server-plugins-connectors-properties-write-back`. Default is true. Module Documentation ==================== .. automodule:: Bcfg2.Server.Plugins.Properties