Merge pull request #44071 from garethgreenaway/various_beacon_fixes

[develop] Various fixes to beacons
This commit is contained in:
Nicole Thomas 2017-10-20 11:06:27 -04:00 committed by GitHub
commit 012477071f
4 changed files with 139 additions and 35 deletions

View File

@ -199,13 +199,42 @@ class Beacon(object):
else:
self.opts['beacons'][name].append({'enabled': enabled_value})
def list_beacons(self):
def _get_beacons(self,
include_opts=True,
include_pillar=True):
'''
Return the beacons data structure
'''
beacons = {}
if include_pillar:
pillar_beacons = self.opts.get('pillar', {}).get('beacons', {})
if not isinstance(pillar_beacons, dict):
raise ValueError('Beacons must be of type dict.')
beacons.update(pillar_beacons)
if include_opts:
opts_beacons = self.opts.get('beacons', {})
if not isinstance(opts_beacons, dict):
raise ValueError('Beacons must be of type dict.')
beacons.update(opts_beacons)
return beacons
def list_beacons(self,
include_pillar=True,
include_opts=True):
'''
List the beacon items
include_pillar: Whether to include beacons that are
configured in pillar, default is True.
include_opts: Whether to include beacons that are
configured in opts, default is True.
'''
beacons = self._get_beacons(include_pillar, include_opts)
# Fire the complete event back along with the list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': True, 'beacons': beacons},
tag='/salt/minion/minion_beacons_list_complete')
return True
@ -236,8 +265,8 @@ class Beacon(object):
del beacon_data['enabled']
valid, vcomment = self.beacons[validate_str](beacon_data)
else:
log.info('Beacon %s does not have a validate'
' function, skipping validation.', name)
vcomment = 'Beacon {0} does not have a validate' \
' function, skipping validation.'.format(name)
valid = True
# Fire the complete event back along with the list of beacons
@ -257,16 +286,23 @@ class Beacon(object):
data = {}
data[name] = beacon_data
if name in self.opts['beacons']:
log.info('Updating settings for beacon '
'item: %s', name)
if name in self._get_beacons(include_opts=False):
comment = 'Cannot update beacon item {0}, ' \
'because it is configured in pillar.'.format(name)
complete = False
else:
log.info('Added new beacon item %s', name)
self.opts['beacons'].update(data)
if name in self.opts['beacons']:
comment = 'Updating settings for beacon ' \
'item: {0}'.format(name)
else:
comment = 'Added new beacon item: {0}'.format(name)
complete = True
self.opts['beacons'].update(data)
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_add_complete')
return True
@ -279,13 +315,20 @@ class Beacon(object):
data = {}
data[name] = beacon_data
log.info('Updating settings for beacon '
'item: %s', name)
self.opts['beacons'].update(data)
if name in self._get_beacons(include_opts=False):
comment = 'Cannot modify beacon item {0}, ' \
'it is configured in pillar.'.format(name)
complete = False
else:
comment = 'Updating settings for beacon ' \
'item: {0}'.format(name)
complete = True
self.opts['beacons'].update(data)
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_modify_complete')
return True
@ -295,13 +338,22 @@ class Beacon(object):
Delete a beacon item
'''
if name in self.opts['beacons']:
log.info('Deleting beacon item %s', name)
del self.opts['beacons'][name]
if name in self._get_beacons(include_opts=False):
comment = 'Cannot delete beacon item {0}, ' \
'it is configured in pillar.'.format(name)
complete = False
else:
if name in self.opts['beacons']:
del self.opts['beacons'][name]
comment = 'Deleting beacon item: {0}'.format(name)
else:
comment = 'Beacon item {0} not found.'.format(name)
complete = True
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_delete_complete')
return True
@ -339,11 +391,19 @@ class Beacon(object):
Enable a beacon
'''
self._update_enabled(name, True)
if name in self._get_beacons(include_opts=False):
comment = 'Cannot enable beacon item {0}, ' \
'it is configured in pillar.'.format(name)
complete = False
else:
self._update_enabled(name, True)
comment = 'Enabling beacon item {0}'.format(name)
complete = True
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_enabled_complete')
return True
@ -353,11 +413,19 @@ class Beacon(object):
Disable a beacon
'''
self._update_enabled(name, False)
if name in self._get_beacons(include_opts=False):
comment = 'Cannot disable beacon item {0}, ' \
'it is configured in pillar.'.format(name)
complete = False
else:
self._update_enabled(name, False)
comment = 'Disabling beacon item {0}'.format(name)
complete = True
# Fire the complete event back along with updated list of beacons
evt = salt.utils.event.get_event('minion', opts=self.opts)
evt.fire_event({'complete': True, 'beacons': self.opts['beacons']},
evt.fire_event({'complete': complete, 'comment': comment,
'beacons': self.opts['beacons']},
tag='/salt/minion/minion_beacon_disabled_complete')
return True

View File

@ -2063,6 +2063,8 @@ class Minion(MinionBase):
func = data.get(u'func', None)
name = data.get(u'name', None)
beacon_data = data.get(u'beacon_data', None)
include_pillar = data.get(u'include_pillar', None)
include_opts = data.get(u'include_opts', None)
if func == u'add':
self.beacons.add_beacon(name, beacon_data)
@ -2079,7 +2081,7 @@ class Minion(MinionBase):
elif func == u'disable_beacon':
self.beacons.disable_beacon(name)
elif func == u'list':
self.beacons.list_beacons()
self.beacons.list_beacons(include_opts, include_pillar)
elif func == u'list_available':
self.beacons.list_available_beacons()
elif func == u'validate_beacon':

View File

@ -28,12 +28,22 @@ __func_alias__ = {
}
def list_(return_yaml=True):
def list_(return_yaml=True,
include_pillar=True,
include_opts=True):
'''
List the beacons currently configured on the minion
:param return_yaml: Whether to return YAML formatted output, default True
:return: List of currently configured Beacons.
:param return_yaml: Whether to return YAML formatted output,
default True
:param include_pillar: Whether to include beacons that are
configured in pillar, default is True.
:param include_opts: Whether to include beacons that are
configured in opts, default is True.
:return: List of currently configured Beacons.
CLI Example:
@ -46,7 +56,10 @@ def list_(return_yaml=True):
try:
eventer = salt.utils.event.get_event('minion', opts=__opts__)
res = __salt__['event.fire']({'func': 'list'}, 'manage_beacons')
res = __salt__['event.fire']({'func': 'list',
'include_pillar': include_pillar,
'include_opts': include_opts},
'manage_beacons')
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacons_list_complete', wait=30)
log.debug('event_ret {0}'.format(event_ret))
@ -133,6 +146,10 @@ def add(name, beacon_data, **kwargs):
ret['comment'] = 'Beacon {0} is already configured.'.format(name)
return ret
if name not in list_available(return_yaml=False):
ret['comment'] = 'Beacon "{0}" is not available.'.format(name)
return ret
if 'test' in kwargs and kwargs['test']:
ret['result'] = True
ret['comment'] = 'Beacon: {0} would be added.'.format(name)
@ -170,7 +187,10 @@ def add(name, beacon_data, **kwargs):
if name in beacons and beacons[name] == beacon_data:
ret['result'] = True
ret['comment'] = 'Added beacon: {0}.'.format(name)
return ret
else:
ret['result'] = False
ret['comment'] = event_ret['comment']
return ret
except KeyError:
# Effectively a no-op, since we can't really return without an event system
ret['comment'] = 'Event module not available. Beacon add failed.'
@ -262,7 +282,10 @@ def modify(name, beacon_data, **kwargs):
if name in beacons and beacons[name] == beacon_data:
ret['result'] = True
ret['comment'] = 'Modified beacon: {0}.'.format(name)
return ret
else:
ret['result'] = False
ret['comment'] = event_ret['comment']
return ret
except KeyError:
# Effectively a no-op, since we can't really return without an event system
ret['comment'] = 'Event module not available. Beacon add failed.'
@ -299,12 +322,14 @@ def delete(name, **kwargs):
if res:
event_ret = eventer.get_event(tag='/salt/minion/minion_beacon_delete_complete', wait=30)
if event_ret and event_ret['complete']:
log.debug('== event_ret {} =='.format(event_ret))
beacons = event_ret['beacons']
if name not in beacons:
ret['result'] = True
ret['comment'] = 'Deleted beacon: {0}.'.format(name)
return ret
else:
ret['result'] = False
ret['comment'] = event_ret['comment']
except KeyError:
# Effectively a no-op, since we can't really return without an event system
ret['comment'] = 'Event module not available. Beacon add failed.'
@ -327,7 +352,7 @@ def save():
ret = {'comment': [],
'result': True}
beacons = list_(return_yaml=False)
beacons = list_(return_yaml=False, include_pillar=False)
# move this file into an configurable opt
sfn = '{0}/{1}/beacons.conf'.format(__opts__['config_dir'],
@ -380,7 +405,7 @@ def enable(**kwargs):
else:
ret['result'] = False
ret['comment'] = 'Failed to enable beacons on minion.'
return ret
return ret
except KeyError:
# Effectively a no-op, since we can't really return without an event system
ret['comment'] = 'Event module not available. Beacons enable job failed.'
@ -420,7 +445,7 @@ def disable(**kwargs):
else:
ret['result'] = False
ret['comment'] = 'Failed to disable beacons on minion.'
return ret
return ret
except KeyError:
# Effectively a no-op, since we can't really return without an event system
ret['comment'] = 'Event module not available. Beacons enable job failed.'
@ -483,7 +508,10 @@ def enable_beacon(name, **kwargs):
else:
ret['result'] = False
ret['comment'] = 'Failed to enable beacon {0} on minion.'.format(name)
return ret
else:
ret['result'] = False
ret['comment'] = event_ret['comment']
return ret
except KeyError:
# Effectively a no-op, since we can't really return without an event system
ret['comment'] = 'Event module not available. Beacon enable job failed.'
@ -536,7 +564,10 @@ def disable_beacon(name, **kwargs):
else:
ret['result'] = False
ret['comment'] = 'Failed to disable beacon on minion.'
return ret
else:
ret['result'] = False
ret['comment'] = event_ret['comment']
return ret
except KeyError:
# Effectively a no-op, since we can't really return without an event system
ret['comment'] = 'Event module not available. Beacon disable job failed.'

View File

@ -59,6 +59,9 @@ class BeaconsTestCase(TestCase, LoaderModuleMockMixin):
event_returns = [{'complete': True,
'tag': '/salt/minion/minion_beacons_list_complete',
'beacons': {}},
{'complete': True,
'tag': '/salt/minion/minion_beacons_list_available_complete',
'beacons': ['ps']},
{'complete': True,
'valid': True,
'vcomment': '',