mirror of
https://github.com/xcat2/confluent.git
synced 2025-06-16 19:30:29 +00:00
Have configmanager protect against unrecognized data.
When doing a set, check the keynames and value types as appropriate. raise ValueError in the configmanager case since it could be code or human mistake. attributes plugin then catches this error and propogates it up as an InvalidArgumentException if it is just trying to pass in data from user.
This commit is contained in:
@ -54,7 +54,7 @@ node = {
|
||||
'groups': {
|
||||
'type': (list, tuple),
|
||||
'default': 'all',
|
||||
'description': ('List of static groups for which this node is'
|
||||
'description': ('List of static groups for which this node is '
|
||||
'considered a member'),
|
||||
},
|
||||
#'type': {
|
||||
@ -128,8 +128,8 @@ node = {
|
||||
# 'serial console configuration')
|
||||
# },
|
||||
'console.method': {
|
||||
'description': ('Indicate the method used to access the console of'
|
||||
'The managed node.')
|
||||
'description': ('Indicate the method used to access the console of '
|
||||
'the managed node.')
|
||||
},
|
||||
# 'virtualization.host': {
|
||||
# 'description': ('Hypervisor where this node does/should reside'),
|
||||
|
@ -54,6 +54,7 @@ from Crypto.Hash import SHA256
|
||||
import array
|
||||
import ast
|
||||
import collections
|
||||
import confluent.config.attributes as attributes
|
||||
import confluent.util
|
||||
import copy
|
||||
import cPickle
|
||||
@ -236,9 +237,9 @@ class _ExpressionFormat(string.Formatter):
|
||||
ast.BitOr: operator.or_,
|
||||
}
|
||||
|
||||
def __init__(self, nodeobj):
|
||||
def __init__(self, nodeobj, nodename):
|
||||
self._nodeobj = nodeobj
|
||||
self._numbers = re.findall(self.nummatch, nodeobj['name']['value'])
|
||||
self._nodename = nodename
|
||||
|
||||
def get_field(self, field_name, args, kwargs):
|
||||
parsed = ast.parse(field_name)
|
||||
@ -246,10 +247,6 @@ class _ExpressionFormat(string.Formatter):
|
||||
|
||||
def _handle_ast_node(self, node):
|
||||
if isinstance(node, ast.Num):
|
||||
if '_expressionkeys' not in self._nodeobj:
|
||||
self._nodeobj['_expressionkeys'] = set(['name'])
|
||||
else:
|
||||
self._nodeobj['_expressionkeys'].add('name')
|
||||
return node.n
|
||||
elif isinstance(node, ast.Attribute):
|
||||
#ok, we have something with a dot
|
||||
@ -266,10 +263,12 @@ class _ExpressionFormat(string.Formatter):
|
||||
elif isinstance(node, ast.Name):
|
||||
var = node.id
|
||||
if var == 'nodename':
|
||||
return self._nodeobj['name']['value']
|
||||
return self._nodename
|
||||
mg = re.match(self.posmatch, var)
|
||||
if mg:
|
||||
idx = int(mg.group(1))
|
||||
if self._numbers == None:
|
||||
self._numbers = re.findall(self.nummatch, self._nodename)
|
||||
return int(self._numbers[idx - 1])
|
||||
else:
|
||||
if var in self._nodeobj:
|
||||
@ -471,6 +470,7 @@ class ConfigManager(object):
|
||||
# if the attribute is not set, this will search for a candidate
|
||||
# if it is set, but inheritedfrom, search for a replacement, just
|
||||
# in case
|
||||
print repr(nodecfg['groups'])
|
||||
for group in nodecfg['groups']:
|
||||
if attrib in self._cfgstore['groups'][group]:
|
||||
if srcgroup is not None and group != srcgroup:
|
||||
@ -498,8 +498,7 @@ class ConfigManager(object):
|
||||
elif group not in self._cfgstore['grouplist']:
|
||||
self._cfgstore['grouplist'].append(group)
|
||||
if group not in self._cfgstore['groups']:
|
||||
self._cfgstore['groups'][group] = {'name': {'value': group},
|
||||
'nodes': set([node]) }
|
||||
self._cfgstore['groups'][group] = {'nodes': set([node])}
|
||||
elif 'nodes' not in self._cfgstore['groups'][group]:
|
||||
self._cfgstore['groups'][group]['nodes'] = set([node])
|
||||
elif node not in self._cfgstore['groups'][group]['nodes']:
|
||||
@ -519,8 +518,7 @@ class ConfigManager(object):
|
||||
self._node_removed_from_group(node, group)
|
||||
for node in nodes:
|
||||
if node not in self._cfgstore['nodes']:
|
||||
self._cfgstore['nodes'][node] = {'name': {'value': node},
|
||||
'groups': [group] }
|
||||
self._cfgstore['nodes'][node] = {'groups': [group]}
|
||||
elif 'groups' not in self._cfgstore['nodes'][node]:
|
||||
self._cfgstore['nodes'][node]['groups'] = [group]
|
||||
elif group not in self._cfgstore['nodes'][node]['groups']:
|
||||
@ -534,7 +532,7 @@ class ConfigManager(object):
|
||||
self._cfgstore['groups'] = {}
|
||||
for group in attribmap.iterkeys():
|
||||
if group not in self._cfgstore['groups']:
|
||||
self._cfgstore['groups'][group] = {'name': {'value': group}, 'nodes': set([])}
|
||||
self._cfgstore['groups'][group] = {'nodes': set([])}
|
||||
cfgobj = self._cfgstore['groups'][group]
|
||||
for attr in attribmap[group].iterkeys():
|
||||
newdict = {}
|
||||
@ -571,11 +569,14 @@ class ConfigManager(object):
|
||||
# flows to peers, all should have the same result
|
||||
for node in attribmap.iterkeys():
|
||||
if node not in self._cfgstore['nodes']:
|
||||
self._cfgstore['nodes'][node] = {'name': {'value': node}}
|
||||
self._cfgstore['nodes'][node] = {}
|
||||
cfgobj = self._cfgstore['nodes'][node]
|
||||
exprmgr = _ExpressionFormat(cfgobj)
|
||||
recalcexpressions = False
|
||||
for attrname in attribmap[node].iterkeys():
|
||||
if (attrname not in attributes.node or
|
||||
('type' in attributes.node[attrname] and
|
||||
type(attribmap[node][attrname]) not in attributes.node[attrname])):
|
||||
raise ValueError
|
||||
newdict = {}
|
||||
if (isinstance(attribmap[node][attrname], str)):
|
||||
newdict = {'value': attribmap[node][attrname] }
|
||||
@ -592,10 +593,13 @@ class ConfigManager(object):
|
||||
attrname in cfgobj['_expressionkeys']):
|
||||
recalcexpressions = True
|
||||
if 'expression' in cfgobj[attrname]: # evaluate now
|
||||
if exprmgr is None:
|
||||
exprmgr = _ExpressionFormat(cfgobj, node)
|
||||
cfgobj[attrname] = _decode_attribute(attrname, cfgobj,
|
||||
formatter=exprmgr)
|
||||
if recalcexpressions:
|
||||
exprmgr = _ExpressionFormat(cfgobj)
|
||||
if exprmgr is None:
|
||||
exprmgr = _ExpressionFormat(cfgobj, node)
|
||||
self._recalculate_expressions(cfgobj, formatter=exprmgr)
|
||||
self._bg_sync_to_file()
|
||||
#TODO: wait for synchronization to suceed/fail??)
|
||||
|
@ -35,10 +35,6 @@ class ConfluentMessage(object):
|
||||
val = self.kvpairs[key]
|
||||
value = self.defaultvalue
|
||||
type = self.defaulttype
|
||||
try:
|
||||
desc = self.desc
|
||||
except:
|
||||
desc = ''
|
||||
if 'value' in val:
|
||||
value = val['value']
|
||||
if value is None:
|
||||
@ -52,17 +48,17 @@ class ConfluentMessage(object):
|
||||
for v in val:
|
||||
snippet += ('<input type="{0}" name="{1}" value="{2}" '
|
||||
' "title="{3}">'
|
||||
).format(type, key, v, desc)
|
||||
).format(type, key, v, self.desc)
|
||||
snippet += (
|
||||
'<input type="{0}" name="{1}" value="" title="{2}">'
|
||||
'<input type="checkbox" name="restexplorerhonorkey" '
|
||||
'value="{1}">').format(type, key, desc)
|
||||
'value="{1}">').format(type, key, self.desc)
|
||||
return snippet
|
||||
snippet += (key + ":" +
|
||||
'<input type="{0}" name="{1}" value="{2}" '
|
||||
'title="{3}"><input type="checkbox" '
|
||||
'name="restexplorerhonorkey" value="{1}">'
|
||||
).format(type, key, value, desc)
|
||||
).format(type, key, value, self.desc)
|
||||
return snippet
|
||||
|
||||
|
||||
@ -264,7 +260,7 @@ class PowerState(ConfluentChoiceMessage):
|
||||
|
||||
|
||||
class Attributes(ConfluentMessage):
|
||||
def __init__(self, node=None, kv=None, desc=None):
|
||||
def __init__(self, node=None, kv=None, desc=''):
|
||||
self.desc = desc
|
||||
nkv = {}
|
||||
for key in kv.iterkeys():
|
||||
@ -278,7 +274,8 @@ class Attributes(ConfluentMessage):
|
||||
|
||||
|
||||
class ListAttributes(ConfluentMessage):
|
||||
def __init__(self, node, kv):
|
||||
def __init__(self, node, kv, desc=''):
|
||||
self.desc = desc
|
||||
self .kvpairs = {
|
||||
node: kv
|
||||
}
|
||||
@ -287,15 +284,17 @@ class ListAttributes(ConfluentMessage):
|
||||
class CryptedAttributes(Attributes):
|
||||
defaulttype = 'password'
|
||||
|
||||
def __init__(self, node=None, kv=None, desc=None):
|
||||
def __init__(self, node=None, kv=None, desc=''):
|
||||
# for now, just keep the dictionary keys and discard crypt value
|
||||
self.desc = desc
|
||||
nkv = {}
|
||||
for key in kv.iterkeys():
|
||||
if kv[key]['cryptvalue'] != '':
|
||||
nkv[key] = {'isset': True}
|
||||
else:
|
||||
nkv[key] = {'isset': False}
|
||||
nkv[key] = {'isset': False}
|
||||
try:
|
||||
if kv[key] is not None and kv[key]['cryptvalue'] != '':
|
||||
nkv[key] = {'isset': True}
|
||||
except KeyError:
|
||||
pass
|
||||
if node is None:
|
||||
self.kvpairs = nkv
|
||||
else:
|
||||
|
@ -1,3 +1,4 @@
|
||||
import confluent.exceptions as exc
|
||||
import confluent.messages as msg
|
||||
import confluent.config.attributes as allattributes
|
||||
|
||||
@ -11,29 +12,35 @@ def retrieve(nodes, element, configmanager, inputdata):
|
||||
elif attribute == 'groups': # no setting, provide a blank
|
||||
val = []
|
||||
else: # no setting, provide a blank
|
||||
val = {'value': '', 'cryptvalue': ''}
|
||||
val = {'value': None}
|
||||
if attribute.startswith('secret.'):
|
||||
yield msg.CryptedAttributes(node,
|
||||
{attribute: val})
|
||||
{attribute: val},
|
||||
allattributes.node[attribute]['description'])
|
||||
elif isinstance(val, list):
|
||||
yield msg.ListAttributes(node,
|
||||
{attribute: val})
|
||||
{attribute: val},
|
||||
allattributes.node[attribute]['description'])
|
||||
else:
|
||||
yield msg.Attributes(node,
|
||||
{attribute: val['value']})
|
||||
{attribute: val['value']},
|
||||
allattributes.node[attribute]['description'])
|
||||
elif element[-1] == 'current':
|
||||
for node in attributes.iterkeys():
|
||||
for attribute in sorted(attributes[node].iterkeys()):
|
||||
currattr = attributes[node][attribute]
|
||||
if 'value' in currattr:
|
||||
yield msg.Attributes(node,
|
||||
{attribute: currattr['value']})
|
||||
{attribute: currattr['value']},
|
||||
allattributes.node[attribute]['description'])
|
||||
elif 'cryptvalue' in currattr:
|
||||
yield msg.CryptedAttributes(node,
|
||||
{attribute: currattr})
|
||||
{attribute: currattr},
|
||||
allattributes.node[attribute]['description'])
|
||||
elif isinstance(currattr, list):
|
||||
yield msg.ListAttributes(node,
|
||||
{attribute: currattr})
|
||||
{attribute: currattr},
|
||||
allattributes.node[attribute]['description'])
|
||||
else:
|
||||
print repr(currattr)
|
||||
raise Exception("BUGGY ATTRIBUTE FOR NODE")
|
||||
@ -45,5 +52,8 @@ def update(nodes, element, configmanager, inputdata):
|
||||
updatenode = inputdata.get_attributes(node)
|
||||
if updatenode:
|
||||
updatedict[node] = updatenode
|
||||
configmanager.set_node_attributes(updatedict)
|
||||
try:
|
||||
configmanager.set_node_attributes(updatedict)
|
||||
except ValueError:
|
||||
raise exc.InvalidArgumentException()
|
||||
return retrieve(nodes, element, configmanager, inputdata)
|
||||
|
Reference in New Issue
Block a user