%PDF- %PDF-
Direktori : /usr/lib/python2.7/site-packages/salt/runners/ |
Current File : //usr/lib/python2.7/site-packages/salt/runners/survey.py |
# -*- coding: utf-8 -*- ''' A general map/reduce style salt runner for aggregating results returned by several different minions. .. versionadded:: 2014.7.0 Aggregated results are sorted by the size of the minion pools which returned matching results. Useful for playing the game: *"some of these things are not like the others..."* when identifying discrepancies in a large infrastructure managed by salt. ''' # Import python libs from __future__ import absolute_import, print_function, unicode_literals # Import salt libs import salt.client from salt.exceptions import SaltClientError # Import 3rd-party libs from salt.ext import six from salt.ext.six.moves import range def hash(*args, **kwargs): ''' Return the MATCHING minion pools from the aggregated and sorted results of a salt command .. versionadded:: 2014.7.0 This command is submitted via a salt runner using the general form:: salt-run survey.hash [survey_sort=up/down] <target> <salt-execution-module> <salt-execution-module parameters> Optionally accept a ``survey_sort=`` parameter. Default: ``survey_sort=down`` CLI Example #1: (functionally equivalent to ``salt-run manage.up``) .. code-block:: bash salt-run survey.hash "*" test.ping CLI Example #2: (find an "outlier" minion config file) .. code-block:: bash salt-run survey.hash "*" file.get_hash /etc/salt/minion survey_sort=up ''' return _get_pool_results(*args, **kwargs) def diff(*args, **kwargs): ''' Return the DIFFERENCE of the result sets returned by each matching minion pool .. versionadded:: 2014.7.0 These pools are determined from the aggregated and sorted results of a salt command. This command displays the "diffs" as a series of 2-way differences -- namely the difference between the FIRST displayed minion pool (according to sort order) and EACH SUBSEQUENT minion pool result set. Differences are displayed according to the Python ``difflib.unified_diff()`` as in the case of the salt execution module ``file.get_diff``. This command is submitted via a salt runner using the general form:: salt-run survey.diff [survey_sort=up/down] <target> <salt-execution-module> <salt-execution-module parameters> Optionally accept a ``survey_sort=`` parameter. Default: ``survey_sort=down`` CLI Example #1: (Example to display the "differences of files") .. code-block:: bash salt-run survey.diff survey_sort=up "*" cp.get_file_str file:///etc/hosts ''' # TODO: The salt execution module "cp.get_file_str file:///..." is a # non-obvious way to display the differences between files using # survey.diff . A more obvious method needs to be found or developed. import difflib bulk_ret = _get_pool_results(*args, **kwargs) is_first_time = True for k in bulk_ret: print('minion pool :\n' '------------') print(k['pool']) print('pool size :\n' '----------') print(' ' + six.text_type(len(k['pool']))) if is_first_time: is_first_time = False print('pool result :\n' '------------') print(' ' + bulk_ret[0]['result']) print() continue outs = ('differences from "{0}" results :').format( bulk_ret[0]['pool'][0]) print(outs) print('-' * (len(outs) - 1)) from_result = bulk_ret[0]['result'].splitlines() for i in range(0, len(from_result)): from_result[i] += '\n' to_result = k['result'].splitlines() for i in range(0, len(to_result)): to_result[i] += '\n' outs = '' outs += ''.join(difflib.unified_diff(from_result, to_result, fromfile=bulk_ret[0]['pool'][0], tofile=k['pool'][0], n=0)) print(outs) print() return bulk_ret def _get_pool_results(*args, **kwargs): ''' A helper function which returns a dictionary of minion pools along with their matching result sets. Useful for developing other "survey style" functions. Optionally accepts a "survey_sort=up" or "survey_sort=down" kwargs for specifying sort order. Because the kwargs namespace of the "salt" and "survey" command are shared, the name "survey_sort" was chosen to help avoid option conflicts. ''' # TODO: the option "survey.sort=" would be preferred for namespace # separation but the kwargs parser for the salt-run command seems to # improperly pass the options containing a "." in them for later modules to # process. The "_" is used here instead. import hashlib tgt = args[0] cmd = args[1] ret = {} sort = kwargs.pop('survey_sort', 'down') direction = sort != 'up' tgt_type = kwargs.pop('tgt_type', 'compound') if tgt_type not in ['compound', 'pcre']: tgt_type = 'compound' kwargs_passthru = dict((k, kwargs[k]) for k in six.iterkeys(kwargs) if not k.startswith('_')) client = salt.client.get_local_client(__opts__['conf_file']) try: minions = client.cmd(tgt, cmd, args[2:], timeout=__opts__['timeout'], tgt_type=tgt_type, kwarg=kwargs_passthru) except SaltClientError as client_error: print(client_error) return ret # hash minion return values as a string for minion in sorted(minions): digest = hashlib.sha256(six.text_type(minions[minion]).encode(__salt_system_encoding__)).hexdigest() if digest not in ret: ret[digest] = {} ret[digest]['pool'] = [] ret[digest]['result'] = six.text_type(minions[minion]) ret[digest]['pool'].append(minion) sorted_ret = [] for k in sorted(ret, key=lambda k: len(ret[k]['pool']), reverse=direction): # return aggregated results, sorted by size of the hash pool sorted_ret.append(ret[k]) return sorted_ret