From f2c09795ffa70c9b4da20fc4a5504b7fa46e99a2 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Wed, 19 Feb 2014 20:24:51 -0500 Subject: [PATCH] Fix expression based callout of other keys The '_' prefixed attributes suggest more care should be taken. --- confluent/config/configmanager.py | 19 +++++++++++-------- confluent/messages.py | 12 +++++++++++- plugins/configuration/attributes.py | 13 ++++++++++++- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/confluent/config/configmanager.py b/confluent/config/configmanager.py index 5276c38d..d9ab964d 100644 --- a/confluent/config/configmanager.py +++ b/confluent/config/configmanager.py @@ -240,6 +240,7 @@ class _ExpressionFormat(string.Formatter): def __init__(self, nodeobj, nodename): self._nodeobj = nodeobj self._nodename = nodename + self._numbers = None def get_field(self, field_name, args, kwargs): parsed = ast.parse(field_name) @@ -256,7 +257,7 @@ class _ExpressionFormat(string.Formatter): if '_expressionkeys' not in self._nodeobj: self._nodeobj['_expressionkeys'] = set([key]) else: - self._nodeobj['_expressionkeys'].add([key]) + self._nodeobj['_expressionkeys'].add(key) val = _decode_attribute(key, self._nodeobj, formatter=self) return val['value'] if 'value' in val else "" @@ -452,7 +453,7 @@ class ConfigManager(object): except KeyError: # something did not exist, nothing to do return for attrib in groupcfg.iterkeys(): - self._do_inheritance(nodecfg, attrib) + self._do_inheritance(nodecfg, attrib, node) def _node_removed_from_group(self, node, group): try: @@ -460,16 +461,18 @@ class ConfigManager(object): except KeyError: # node did not exist, nothing to do return for attrib in nodecfg.keys(): + if attrib.startswith("_"): + continue if attrib == 'groups': continue try: if nodecfg[attrib]['inheritedfrom'] == group: del nodecfg[attrib] # remove invalid inherited data - self._do_inheritance(nodecfg, attrib) + self._do_inheritance(nodecfg, attrib, node) except KeyError: # inheritedfrom not set, move on pass - def _do_inheritance(self, nodecfg, attrib, srcgroup=None): + def _do_inheritance(self, nodecfg, attrib, nodename, srcgroup=None): # for now, just do single inheritance # TODO: concatenating inheritance if requested if attrib in ('nodes', 'groups'): @@ -488,7 +491,7 @@ class ConfigManager(object): nodecfg[attrib] = \ copy.deepcopy(self._cfgstore['groups'][group][attrib]) nodecfg[attrib]['inheritedfrom'] = group - self._refresh_nodecfg(nodecfg, attrib) + self._refresh_nodecfg(nodecfg, attrib, nodename) return if srcgroup is not None and group == srcgroup: # break out @@ -568,10 +571,10 @@ class ConfigManager(object): else: # update inheritence for node in cfgobj['nodes']: nodecfg = self._cfgstore['nodes'][node] - self._do_inheritance(nodecfg, attr, group) + self._do_inheritance(nodecfg, attr, node, srcgroup=group) self._bg_sync_to_file() - def _refresh_nodecfg(self, cfgobj, attrname): + def _refresh_nodecfg(self, cfgobj, attrname, node): exprmgr = None if 'expression' in cfgobj[attrname]: # evaluate now if exprmgr is None: @@ -613,7 +616,7 @@ class ConfigManager(object): # if the attribute is set and not inherited, # delete it and check for inheritence to backfil data del nodek[attrib] - self._do_inheritance(nodek, attrib) + self._do_inheritance(nodek, attrib, node) self._bg_sync_to_file() def set_node_attributes(self, attribmap): diff --git a/confluent/messages.py b/confluent/messages.py index 957cb9b5..827dd766 100644 --- a/confluent/messages.py +++ b/confluent/messages.py @@ -37,6 +37,8 @@ class ConfluentMessage(object): type = self.defaulttype if val is not None and 'value' in val: value = val['value'] + elif val is not None and 'expression' in val: + value = val['expression'] if value is None: value = '' if val is not None and value == '' and 'isset' in val and val['isset'] is True: @@ -152,6 +154,10 @@ class InputAttributes(ConfluentMessage): raise exc.InvalidArgumentException if nodes is None: self.attribs = inputdata + for attrib in self.attribs: + if (type(self.attribs[attrib]) == str and + '{' in self.attribs[attrib]): + self.attribs[attrib] = {'expression': self.attribs[attrib]} return for node in nodes: if node in inputdata: @@ -168,7 +174,11 @@ class InputAttributes(ConfluentMessage): def get_attributes(self, node): if node not in self.nodeattribs: return {} - return self.nodeattribs[node] + nodeattr = self.nodeattribs[node] + for attr in nodeattr: + if type(nodeattr[attr]) == str and '{' in nodeattr[attr]: + nodeattr[attr] = {'expression': nodeattr[attr]} + return nodeattr class InputPowerMessage(ConfluentMessage): diff --git a/plugins/configuration/attributes.py b/plugins/configuration/attributes.py index cc5e37ae..1f558044 100644 --- a/plugins/configuration/attributes.py +++ b/plugins/configuration/attributes.py @@ -32,10 +32,12 @@ def retrieve_nodegroup(nodegroup, element, configmanager, inputdata): raise Exception("TODO") else: yield msg.Attributes( - kv={attribute: val['value']}, + kv={attribute: val}, desc=allattributes.node[attribute]['description']) if element == 'current': for attribute in sorted(grpcfg.iterkeys()): + if attribute.startswith("_"): + continue currattr = grpcfg[attribute] desc="" if attribute == 'nodes': @@ -62,6 +64,8 @@ def retrieve_nodegroup(nodegroup, element, configmanager, inputdata): kv={attribute: currattr}, desc=desc) else: + print attribute + print repr(currattr) raise Exception("BUGGY ATTRIBUTE FOR NODE") @@ -70,6 +74,9 @@ def retrieve_nodes(nodes, element, configmanager, inputdata): if element[-1] == 'all': for node in nodes: for attribute in sorted(allattributes.node.iterkeys()): + if attribute.startswith("_"): + # a 'private' attribute + continue if attribute in attributes[node]: #have a setting for it val = attributes[node][attribute] elif attribute == 'groups': # no setting, provide a blank @@ -91,6 +98,8 @@ def retrieve_nodes(nodes, element, configmanager, inputdata): elif element[-1] == 'current': for node in attributes.iterkeys(): for attribute in sorted(attributes[node].iterkeys()): + if attribute.startswith("_"): + continue currattr = attributes[node][attribute] try: desc = allattributes.node[attribute]['description'] @@ -107,6 +116,8 @@ def retrieve_nodes(nodes, element, configmanager, inputdata): yield msg.ListAttributes(node, {attribute: currattr}, desc) else: + print attribute + print repr(currattr) raise Exception("BUGGY ATTRIBUTE FOR NODE")