Skip to content

Commit

Permalink
Match class mappings against entity name incl. subdir
Browse files Browse the repository at this point in the history
If a node is defined in a subdirectory, then match class mappings
against the entire (relative) path of the node, including its
subdirectory.

For instance, you might have your nodes arranged in subdirectories
according to the datacentre that they are in:

  - zurich/host1.example.ch
  - zurich/host2.example.ch
  - munich/host1.example.de
  - munich/host2.example.de

A class mapping such as

  /^([^\/]+)\// hosted-in-\\1

would now automatically assign the hosted-in-zurich and hosted-in-munich
classes to the hosts, according to which subdirectory their (yaml_fs)
files reside in.

The information is transported in the so-called entity name, so other
storage backends can also introduce such "tags", they need not be
related to a filesystem path.

Signed-off-by: martin f. krafft <madduck@madduck.net>
  • Loading branch information
madduck committed Dec 10, 2013
1 parent 010ea27 commit 37b56b6
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 16 deletions.
13 changes: 6 additions & 7 deletions doc/source/operations.rst
Expand Up @@ -43,8 +43,8 @@ parameters key-value pairs to set defaults in class definitions, override
Nodes may be defined in subdirectories. However, node names (filename) must be
unique across all subdirectories, and |reclass| will exit with an error if
a node is defined multiple times. Subdirectories therefore really only exist
for the administrator's sanity (and may be used in the future to tag
additional classes onto nodes).
for the administrator's local data structuring. They may be used in mappings
(see below) to tag additional classes onto nodes.

Data merging
------------
Expand Down Expand Up @@ -112,13 +112,12 @@ are used, although they need to be escaped, e.g.::
- /\.(\S+)$/ tld-\\1

Furthermore, since the outer slashes ('/') are used to "quote" the regular
expression, *any* slashes within the regular expression must be escaped::
expression, *any* slashes within the regular expression must be escaped. For
instance, the following class mapping assigns a ``subdir-X`` class to all
nodes that are defined in a subdirectory (using yaml_fs).

class_mappings:
- /^([^\/]+)\// \\1

This is a bit theoretical right now, as nodenames cannot (yet) include
slashes, but that might come…
- /^([^\/]+)\// subdir-\\1

Parameter interpolation
------------------------
Expand Down
8 changes: 5 additions & 3 deletions reclass/storage/__init__.py
Expand Up @@ -119,13 +119,15 @@ def _recurse_entity(self, entity, merge_base=None, seen=None, nodename=None):

def _nodeinfo(self, nodename):
node_entity = self._get_node(nodename)
merge_base = self._populate_with_class_mappings(nodename)
ret = self._recurse_entity(node_entity, merge_base, nodename=nodename)
merge_base = self._populate_with_class_mappings(node_entity.name)
ret = self._recurse_entity(node_entity, merge_base,
nodename=node_entity.name)
ret.interpolate()
return ret

def _nodeinfo_as_dict(self, nodename, entity):
ret = {'__reclass__' : {'node': nodename, 'uri': entity.uri,
ret = {'__reclass__' : {'node': entity.name, 'name': nodename,
'uri': entity.uri,
'timestamp': _get_timestamp()
},
}
Expand Down
8 changes: 5 additions & 3 deletions reclass/storage/yaml_fs/__init__.py
Expand Up @@ -55,11 +55,13 @@ def register_fn(dirpath, filenames):
def _get_node(self, name):
vvv('GET NODE {0}'.format(name))
try:
path = os.path.join(self.nodes_uri, self._nodes[name])
relpath = self._nodes[name]
path = os.path.join(self.nodes_uri, relpath)
name = os.path.splitext(relpath)[0]
except KeyError, e:
raise reclass.errors.NodeNotFound(self._get_storage_name(),
name, self.nodes_uri)
entity = YamlFile(path).entity
entity = YamlFile(path).get_entity(name)
return entity

def _get_class(self, name, nodename=None):
Expand All @@ -70,7 +72,7 @@ def _get_class(self, name, nodename=None):
raise reclass.errors.ClassNotFound(self._get_storage_name(),
name, self.classes_uri,
nodename)
entity = YamlFile(path).entity
entity = YamlFile(path).get_entity()
return entity

def _list_inventory(self):
Expand Down
8 changes: 5 additions & 3 deletions reclass/storage/yaml_fs/yamlfile.py
Expand Up @@ -31,7 +31,7 @@ def _read(self):
self._data = data
fp.close()

def _get_entity(self):
def get_entity(self, name=None):
classes = self._data.get('classes')
if classes is None:
classes = []
Expand All @@ -47,10 +47,12 @@ def _get_entity(self):
parameters = {}
parameters = datatypes.Parameters(parameters)

if name is None:
name = self._path

return datatypes.Entity(classes, applications, parameters,
name=self._path,
name=name,
uri='yaml_fs://{0}'.format(self._path))
entity = property(lambda self: self._get_entity())

def __repr__(self):
return '<{0} {1}, {2}>'.format(self.__class__.__name__, self._path,
Expand Down

0 comments on commit 37b56b6

Please sign in to comment.