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:

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[<filename>].

The data in property files is accessible via different attributes:

Data Type Data Attribute
XML xdata
JSON json
YAML yaml

For instance, in a 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.

Writing to Properties files

New in version 1.2.0.

If you need to make persistent changes to properties data, you can use the write method of the 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

XML Property Files

The data in an XML property file can be accessed with the xdata attribute, an 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 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 <Properties> 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 <Properties>.

JSON Property Files

New in version 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

New in version 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.

Automatch

New in version 1.3.0.

You can enable 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 lxml.etree._Element objects that contain only matching data. (This makes it impossible to do Writing to Properties files 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 <Properties> 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 <Properties> tag.

If you want to see what XMLMatch()/automatch would produce for a given client on a given Properties file, you can use 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 Bcfg2.Server.Plugins.Properties.PropertyFile objects. With automatch enabled, they are lxml.etree._Element objects.

Encrypted Properties data

New in version 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 Bcfg2 Data Encryption for details on encryption in general, and 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:

Module Documentation

The properties plugin maps property files into client metadata instances.

class Bcfg2.Server.Plugins.Properties.JSONPropertyFile(name, core)[source]

Bases: Bcfg2.Server.Plugin.helpers.FileBacked, Bcfg2.Server.Plugins.Properties.PropertyFile

Handle JSON Properties files.

Index()[source]

Index() is called by HandleEvent() every time the data changes, and parses the data into usable data as required.

validate_data()[source]

Verify that the data in this file is valid.

class Bcfg2.Server.Plugins.Properties.Properties(core)[source]

Bases: Bcfg2.Server.Plugin.base.Plugin, Bcfg2.Server.Plugin.interfaces.Connector, Bcfg2.Server.Plugin.helpers.DirectoryBacked

The properties plugin maps property files into client metadata instances.

Parameters:core (Bcfg2.Server.Core) – The Bcfg2.Server.Core initializing the plugin
Raises:OSError if adding a file monitor failed; Bcfg2.Server.Plugin.exceptions.PluginInitError on other errors
Debuggable.__rmi__ = ['toggle_debug', 'set_debug']

List of names of methods to be exposed as XML-RPC functions, if applicable to the child class

extensions = ['xml', 'json']

Extensions that are understood by Properties.

get_additional_data(metadata)[source]

Return arbitrary additional data for the given ClientMetadata object. By convention this is usually a dict object, but doesn’t need to be.

Parameters:metadata (Bcfg2.Server.Plugins.Metadata.ClientMetadata) – The client metadata
Returns:dict
ignore = <_sre.SRE_Pattern object>

Ignore XML schema (.xsd) files

patterns = <_sre.SRE_Pattern object>

Only track and include files whose names and paths match this regex. Created on-the-fly based on which libraries are installed (and thus which data formats are supported). Candidates are .xml (always supported), .json, .yaml, and .yml.

property_dispatcher(fname)[source]

Dispatch an event on a Properties file to the appropriate object.

Parameters:fname (string) – The name of the file that received the event
Returns:An object of the appropriate subclass of PropertyFile
class Bcfg2.Server.Plugins.Properties.PropertyFile(name, core)[source]

Bases: object

Base Properties file handler

Parameters:
  • name (string) – The filename of this properties file.
  • core (Bcfg2.Server.Core) – The Bcfg2.Server.Core initializing the Properties plugin
_write()[source]

Write the data in this data structure back to the property file.

get_additional_data(metadata)[source]

Get file data for inclusion in client metadata.

validate_data()[source]

Verify that the data in this file is valid.

write()[source]

Write the data in this data structure back to the property file. This public method performs checking to ensure that writing is possible and then calls _write().

class Bcfg2.Server.Plugins.Properties.XMLPropertyFile(name, core, should_monitor=False)[source]

Bases: Bcfg2.Server.Plugin.helpers.StructFile, Bcfg2.Server.Plugins.Properties.PropertyFile

Handle XML Properties files.

Index()[source]

Index() is called by HandleEvent() every time the data changes, and parses the data into usable data as required.

get_additional_data(metadata)[source]

Get file data for inclusion in client metadata.

validate_data()[source]

ensure that the data in this object validates against the XML schema for this property file (if a schema exists)

class Bcfg2.Server.Plugins.Properties.YAMLPropertyFile(name, core)[source]

Bases: Bcfg2.Server.Plugin.helpers.FileBacked, Bcfg2.Server.Plugins.Properties.PropertyFile

Handle YAML Properties files.

Index()[source]

Index() is called by HandleEvent() every time the data changes, and parses the data into usable data as required.

validate_data()[source]

Verify that the data in this file is valid.