1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
.. -*- mode: rst -*-
.. _server-plugins-connectors-grouplogic:
==========
GroupLogic
==========
.. versionadded:: 1.3.2
GroupLogic is a connector plugin that lets you use an XML Genshi
template to dynamically set additional groups for clients.
Usage
=====
To use the GroupLogic plugin, first do ``mkdir
/var/lib/bcfg2/GroupLogic``. Add ``GroupLogic`` to your ``plugins``
line in ``/etc/bcfg2.conf``. Next, create
``/var/lib/bcfg2/GroupLogic/groups.xml``:
.. code-block:: xml
<GroupLogic xmlns:py="http://genshi.edgewall.org/">
</GroupLogic>
``groups.xml`` is structured very similarly to the
:ref:`server-plugins-grouping-metadata` ``groups.xml``. A Group tag
that contains no children is a declaration of membership; a Group or
Client tag that does contain children is a conditional.
Unlike ``Metadata/groups.xml``, GroupLogic supports genshi templating,
so you can dynamically create groups. ``GroupLogic/groups.xml`` is
rendered for each client, and the groups set in it are added to the
client metadata.
.. note::
Also unlike ``Metadata/groups.xml``, GroupLogic can not be used to
associate bundles with clients directly, or to negate groups. But
you can use GroupLogic to assign a group that is associated with a
bundle in Metadata.
Consider the case where you have four environments -- dev, test,
staging, and production -- and four components to a web application --
the frontend, the API, the database server, and the caching proxy. In
order to make files specific to the component *and* to the
environment, you need groups to describe each combination:
webapp-frontend-dev, webapp-frontend-test, and so on. You *could* do
this in ``Metadata/groups.xml``:
.. code-block:: xml
<Groups>
<Group name="webapp-frontend">
<Group name="dev">
<Group name="webapp-frontend-dev"/>
</Group>
<Group name="test">
<Group name="webapp-frontend-test"/>
</Group>
...
</Group>
<Group name="webapp-api">
...
</Group>
...
</Groups>
Creating the sixteen groups this way is incredibly tedious, and this
is a quite *small* site. GroupLogic can automate this process.
Assume that we've declared the groups thusly in
``Metadata/groups.xml``:
.. code-block:: xml
<Groups>
<Group name="webapp-frontend" category="webapp-component"/>
<Group name="webapp-api" category="webapp-component"/>
<Group name="webapp-db" category="webapp-component"/>
<Group name="webapp-proxy" category="webapp-component"/>
<Group name="dev" category="environment"/>
<Group name="test" category="environment"/>
<Group name="staging" category="environment"/>
<Group name="prod" category="environment"/>
</Groups>
One way to automate the creation of the groups would be to simply
generate the tedious config:
.. code-block:: xml
<GroupLogic xmlns:py="http://genshi.edgewall.org/">
<py:for each="component in metadata.query.all_groups_in_category('webapp-component')">
<Group name="${component}">
<py:for each="env in metadata.query.all_groups_in_category('environment')">
<Group name="${env}">
<Group name="${component}-${env}"/>
</Group>
</py:for>
</Group>
</py:for>
</GroupLogic>
But, since ``GroupLogic/groups.xml`` is rendered for each client
individually, there's a more elegant way to accomplish the same thing:
.. code-block:: xml
<GroupLogic xmlns:py="http://genshi.edgewall.org/">
<?python
component = metadata.group_in_category("webapp-component")
env = metadata.group_in_category("environment")
?>
<py:if test="component and env">
<Group name="${component}-${env}"/>
</py:if>
</GroupLogic>
This gets only the component and environment for the current client,
and, if both are set, sets the single appropriate group.
|