Merge pull request #7303 from dlanderson/mine_delete_issue_7226

Add mine.delete to remove specific mine functions.
This commit is contained in:
Colton Myers 2013-09-18 16:04:04 -07:00
commit 6aee81133a
5 changed files with 183 additions and 38 deletions

View file

@ -946,6 +946,31 @@ class AESFuncs(object):
fp_.write(self.serial.dumps(load['data']))
return True
def _mine_delete(self, load):
'''
Allow the minion to delete a specific function from its own mine
'''
if 'id' not in load or 'fun' not in load:
return False
if not salt.utils.verify.valid_id(self.opts, load['id']):
return False
if self.opts.get('minion_data_cache', False) or self.opts.get('enforce_mine_cache', False):
cdir = os.path.join(self.opts['cachedir'], 'minions', load['id'])
if not os.path.isdir(cdir):
return True
datap = os.path.join(cdir, 'mine.p')
if os.path.isfile(datap):
try:
with salt.utils.fopen(datap, 'r') as fp_:
mine_data = self.serial.load(fp_)
if isinstance(mine_data, dict):
if mine_data.pop(load['fun'], False):
with salt.utils.fopen(datap, 'w+') as fp_:
fp_.write(self.serial.dumps(mine_data))
except OSError:
return False
return True
def _mine_flush(self, load):
'''
Allow the minion to delete all of its own mine contents

View file

@ -155,6 +155,25 @@ def get(tgt, fun, expr_form='glob'):
ret = sreq.send('aes', auth.crypticle.dumps(load))
return auth.crypticle.loads(ret)
def delete(fun):
'''
Remove specific function contents of minion. Returns True on success.
CLI Example:
.. code-block:: bash
salt '*' mine.delete 'network.interfaces'
'''
auth = _auth()
load = {
'cmd': '_mine_delete',
'id': __opts__['id'],
'fun': fun
}
sreq = salt.payload.SREQ(__opts__['master_uri'])
ret = sreq.send('aes', auth.crypticle.dumps(load))
return auth.crypticle.loads(ret)
def flush():
'''

View file

@ -79,7 +79,8 @@ def _clear_cache(tgt=None,
expr_form='glob',
clear_pillar=False,
clear_grains=False,
clear_mine=False):
clear_mine=False,
clear_mine_func=None):
'''
Clear the cached data/files for the targeted minions.
'''
@ -93,7 +94,8 @@ def _clear_cache(tgt=None,
opts=__opts__)
return pillar_util.clear_cached_minion_data(clear_pillar=clear_pillar,
clear_grains=clear_grains,
clear_mine=clear_mine)
clear_mine=clear_mine,
clear_mine_func=clear_mine_func)
def clear_pillar(tgt, expr_form='glob'):
'''
@ -131,6 +133,18 @@ def clear_mine(tgt=None, expr_form='glob'):
'''
return _clear_cache(tgt, expr_form, clear_mine=True)
def clear_mine_func(tgt=None, expr_form='glob', clear_mine_func=None):
'''
Clear the cached mine function data of the targeted minions
CLI Example:
.. code-block:: bash
salt-run cache.clear_mine_func tgt='*',clear_mine_func='network.interfaces'
'''
return _clear_cache(tgt, expr_form, clear_mine_func=clear_mine_func)
def clear_all(tgt=None, expr_form='glob'):
'''
Clear the cached pillar, grains, and mine data of the targeted minions

View file

@ -255,7 +255,8 @@ class MasterPillarUtil(object):
def clear_cached_minion_data(self,
clear_pillar=False,
clear_grains=False,
clear_mine=False):
clear_mine=False,
clear_mine_func=None):
'''
Clear the cached data/files for the targeted minions.
'''
@ -266,6 +267,8 @@ class MasterPillarUtil(object):
clear_what.append('grains')
if clear_mine:
clear_what.append('mine')
if clear_mine_func is not None:
clear_what.append('mine_func: {0!r}'.format(clear_mine_func))
if not len(clear_what):
log.debug('No cached data types specified for clearing.')
return False
@ -274,7 +277,9 @@ class MasterPillarUtil(object):
log.debug('Clearing cached {0} data for: {1}'.format(
', '.join(clear_what),
minion_ids))
if clear_pillar and clear_grains:
if clear_pillar == clear_grains:
# clear_pillar and clear_grains are both True or both False.
# This means we don't deal with pillar/grains caches at all.
grains = {}
pillars = {}
else:
@ -306,7 +311,16 @@ class MasterPillarUtil(object):
with salt.utils.fopen(data_file, 'w+') as fp_:
fp_.write(self.serial.dumps({'pillar': minion_pillar}))
if clear_mine:
# Delete the whole mine file
os.remove(os.path.join(mine_file))
elif clear_mine_func is not None:
# Delete a specific function from the mine file
with salt.utils.fopen(mine_file) as fp_:
mine_data = self.serial.loads(fp_.read())
if isinstance(mine_data, dict):
if mine_data.pop(clear_mine_func, False):
with salt.utils.fopen(mine_file, 'w+') as fp_:
fp_.write(self.serial.dumps(mine_data))
except (OSError, IOError):
return True
return True

View file

@ -19,54 +19,127 @@ class MineTest(integration.ModuleCase):
'''
self.assertTrue(self.run_function('mine.update', minion_tgt='minion'))
self.assertTrue(
self.run_function(
'mine.update',
minion_tgt='sub_minion'
)
)
self.run_function(
'mine.update',
minion_tgt='sub_minion'
)
)
self.assertTrue(
self.run_function(
'mine.get',
['minion', 'test.ping']
)
)
self.run_function(
'mine.get',
['minion', 'test.ping']
)
)
def test_send(self):
'''
test mine.send
'''
self.assertFalse(
self.run_function(
'mine.send',
['foo.__spam_and_cheese']
)
)
self.run_function(
'mine.send',
['foo.__spam_and_cheese']
)
)
self.assertTrue(
self.run_function(
'mine.send',
['grains.items'],
minion_tgt='minion',
)
)
self.run_function(
'mine.send',
['grains.items'],
minion_tgt='minion',
)
)
self.assertTrue(
self.run_function(
'mine.send',
['grains.items'],
minion_tgt='sub_minion',
)
)
self.run_function(
'mine.send',
['grains.items'],
minion_tgt='sub_minion',
)
)
ret = self.run_function(
'mine.get',
['sub_minion', 'grains.items']
)
'mine.get',
['sub_minion', 'grains.items']
)
self.assertEqual(ret['sub_minion']['id'], 'sub_minion')
ret = self.run_function(
'mine.get',
['minion', 'grains.items'],
minion_tgt='sub_minion'
)
'mine.get',
['minion', 'grains.items'],
minion_tgt='sub_minion'
)
self.assertEqual(ret['minion']['id'], 'minion')
def test_mine_flush(self):
'''
Test mine.flush
'''
for minion_id in ('minion', 'sub_minion'):
self.assertTrue(
self.run_function(
'mine.send',
['grains.items'],
minion_tgt=minion_id
)
)
ret = self.run_function(
'mine.get',
[minion_id, 'grains.items'],
minion_tgt=minion_id
)
self.assertEqual(ret[minion_id]['id'], minion_id)
self.assertTrue(
self.run_function(
'mine.flush',
minion_tgt='minion'
)
)
ret_flushed = self.run_function(
'mine.get',
['*', 'grains.items']
)
self.assertEqual(ret_flushed.get('minion', None), None)
self.assertEqual(ret_flushed['sub_minion']['id'], 'sub_minion')
def test_mine_delete(self):
'''
Test mine.delete
'''
self.assertTrue(
self.run_function(
'mine.send',
['grains.items']
)
)
self.assertTrue(
self.run_function(
'mine.send',
['test.echo', 'foo']
)
)
ret_grains = self.run_function(
'mine.get',
['minion', 'grains.items']
)
self.assertEqual(ret_grains['minion']['id'], 'minion')
ret_echo = self.run_function(
'mine.get',
['minion', 'test.echo']
)
self.assertEqual(ret_echo['minion'], 'foo')
self.assertTrue(
self.run_function(
'mine.delete',
['grains.items']
)
)
ret_grains_deleted = self.run_function(
'mine.get',
['minion', 'grains.items']
)
self.assertEqual(ret_grains_deleted.get('minion', None), None)
ret_echo_stays = self.run_function(
'mine.get',
['minion', 'test.echo']
)
self.assertEqual(ret_echo_stays['minion'], 'foo')
if __name__ == '__main__':
from integration import run_tests