diff --git a/salt/roster/flat.py b/salt/roster/flat.py index 9ccb18bc97..8a7fa46d99 100644 --- a/salt/roster/flat.py +++ b/salt/roster/flat.py @@ -4,20 +4,6 @@ Read in the roster from a flat file using the renderer system ''' from __future__ import absolute_import, print_function, unicode_literals -# Import python libs -import fnmatch -import re -import copy - -# Try to import range from https://github.com/ytoolshed/range -HAS_RANGE = False -try: - import seco.range - HAS_RANGE = True -except ImportError: - pass -# pylint: enable=import-error - # Import Salt libs import salt.loader import salt.config @@ -47,122 +33,4 @@ def targets(tgt, tgt_type='glob', **kwargs): conditioned_raw = {} for minion in raw: conditioned_raw[six.text_type(minion)] = salt.config.apply_sdb(raw[minion]) - rmatcher = RosterMatcher(conditioned_raw, tgt, tgt_type, 'ipv4', opts=__opts__) - return rmatcher.targets() - - -class RosterMatcher(object): - ''' - Matcher for the roster data structure - ''' - def __init__(self, raw, tgt, tgt_type, ipv='ipv4', **kwargs): - self.tgt = tgt - self.tgt_type = tgt_type - self.raw = raw - self.ipv = ipv - self.opts = kwargs.get('opts', {}) - - def targets(self): - ''' - Execute the correct tgt_type routine and return - ''' - try: - return getattr(self, 'ret_{0}_minions'.format(self.tgt_type))() - except AttributeError: - return {} - - def ret_glob_minions(self): - ''' - Return minions that match via glob - ''' - minions = {} - for minion in self.raw: - if fnmatch.fnmatch(minion, self.tgt): - data = self.get_data(minion) - if data: - minions[minion] = data.copy() - return minions - - def ret_pcre_minions(self): - ''' - Return minions that match via pcre - ''' - minions = {} - for minion in self.raw: - if re.match(self.tgt, minion): - data = self.get_data(minion) - if data: - minions[minion] = data.copy() - return minions - - def ret_list_minions(self): - ''' - Return minions that match via list - ''' - minions = {} - if not isinstance(self.tgt, list): - self.tgt = self.tgt.split(',') - for minion in self.raw: - if minion in self.tgt: - data = self.get_data(minion) - if data: - minions[minion] = data.copy() - return minions - - def ret_nodegroup_minions(self): - ''' - Return minions which match the special list-only groups defined by - ssh_list_nodegroups - ''' - minions = {} - nodegroup = self.opts.get('ssh_list_nodegroups', {}).get(self.tgt, []) - if not isinstance(nodegroup, list): - nodegroup = nodegroup.split(',') - for minion in self.raw: - if minion in nodegroup: - data = self.get_data(minion) - if data: - minions[minion] = data.copy() - return minions - - def ret_range_minions(self): - ''' - Return minions that are returned by a range query - ''' - if HAS_RANGE is False: - raise RuntimeError("Python lib 'seco.range' is not available") - - minions = {} - range_hosts = _convert_range_to_list(self.tgt, self.opts['range_server']) - - for minion in self.raw: - if minion in range_hosts: - data = self.get_data(minion) - if data: - minions[minion] = data.copy() - return minions - - def get_data(self, minion): - ''' - Return the configured ip - ''' - ret = copy.deepcopy(self.opts.get('roster_defaults', {})) - if isinstance(self.raw[minion], six.string_types): - ret.update({'host': self.raw[minion]}) - return ret - elif isinstance(self.raw[minion], dict): - ret.update(self.raw[minion]) - return ret - return False - - -def _convert_range_to_list(tgt, range_server): - ''' - convert a seco.range range into a list target - ''' - r = seco.range.Range(range_server) - try: - return r.expand(tgt) - except seco.range.RangeException as err: - log.error('Range server exception: %s', err) - return [] + return __utils__['roster_matcher.targets'](conditioned_raw, tgt, tgt_type, 'ipv4') diff --git a/salt/roster/terraform.py b/salt/roster/terraform.py index d57f47f145..ebfae02cbc 100644 --- a/salt/roster/terraform.py +++ b/salt/roster/terraform.py @@ -52,7 +52,7 @@ import os.path # Import Salt libs import salt.utils.files import salt.utils.json -from salt.roster.flat import RosterMatcher +import salt.utils.roster_matcher log = logging.getLogger(__name__) @@ -170,5 +170,4 @@ def targets(tgt, tgt_type='glob', **kwargs): # pylint: disable=W0613 raw = _parse_state_file(roster_file) log.debug('%s hosts in terraform state file', len(raw)) - rmatcher = RosterMatcher(raw, tgt, tgt_type, 'ipv4', opts=__opts__) - return rmatcher.targets() + return salt.utils.roster_matcher.targets(raw, tgt, tgt_type, 'ipv4') diff --git a/salt/utils/roster_matcher.py b/salt/utils/roster_matcher.py new file mode 100644 index 0000000000..145a047498 --- /dev/null +++ b/salt/utils/roster_matcher.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- +''' +Roster matching by various criteria (glob, pcre, etc) +''' +from __future__ import absolute_import, print_function, unicode_literals + +# Import python libs +import fnmatch +import re +import copy + +# Try to import range from https://github.com/ytoolshed/range +HAS_RANGE = False +try: + import seco.range + HAS_RANGE = True +except ImportError: + pass +# pylint: enable=import-error + +# Import Salt libs +import salt.loader +import salt.config +from salt.ext import six +from salt.template import compile_template + +import logging +log = logging.getLogger(__name__) + + +def targets(conditioned_raw, tgt, tgt_type, ipv='ipv4'): + rmatcher = salt.utils.roster_matcher.RosterMatcher(conditioned_raw, tgt, + tgt_type, ipv) + return rmatcher.targets() + + +class RosterMatcher(object): + ''' + Matcher for the roster data structure + ''' + def __init__(self, raw, tgt, tgt_type, ipv='ipv4'): + self.tgt = tgt + self.tgt_type = tgt_type + self.raw = raw + self.ipv = ipv + + def targets(self): + ''' + Execute the correct tgt_type routine and return + ''' + try: + return getattr(self, 'ret_{0}_minions'.format(self.tgt_type))() + except AttributeError: + return {} + + def ret_glob_minions(self): + ''' + Return minions that match via glob + ''' + minions = {} + for minion in self.raw: + if fnmatch.fnmatch(minion, self.tgt): + data = self.get_data(minion) + if data: + minions[minion] = data.copy() + return minions + + def ret_pcre_minions(self): + ''' + Return minions that match via pcre + ''' + minions = {} + for minion in self.raw: + if re.match(self.tgt, minion): + data = self.get_data(minion) + if data: + minions[minion] = data.copy() + return minions + + def ret_list_minions(self): + ''' + Return minions that match via list + ''' + minions = {} + if not isinstance(self.tgt, list): + self.tgt = self.tgt.split(',') + for minion in self.raw: + if minion in self.tgt: + data = self.get_data(minion) + if data: + minions[minion] = data.copy() + return minions + + def ret_nodegroup_minions(self): + ''' + Return minions which match the special list-only groups defined by + ssh_list_nodegroups + ''' + minions = {} + nodegroup = __opts__.get('ssh_list_nodegroups', {}).get(self.tgt, []) + if not isinstance(nodegroup, list): + nodegroup = nodegroup.split(',') + for minion in self.raw: + if minion in nodegroup: + data = self.get_data(minion) + if data: + minions[minion] = data.copy() + return minions + + def ret_range_minions(self): + ''' + Return minions that are returned by a range query + ''' + if HAS_RANGE is False: + raise RuntimeError("Python lib 'seco.range' is not available") + + minions = {} + range_hosts = _convert_range_to_list(self.tgt, __opts__['range_server']) + + for minion in self.raw: + if minion in range_hosts: + data = self.get_data(minion) + if data: + minions[minion] = data.copy() + return minions + + def get_data(self, minion): + ''' + Return the configured ip + ''' + ret = copy.deepcopy(__opts__.get('roster_defaults', {})) + if isinstance(self.raw[minion], six.string_types): + ret.update({'host': self.raw[minion]}) + return ret + elif isinstance(self.raw[minion], dict): + ret.update(self.raw[minion]) + return ret + return False + + +def _convert_range_to_list(tgt, range_server): + ''' + convert a seco.range range into a list target + ''' + r = seco.range.Range(range_server) + try: + return r.expand(tgt) + except seco.range.RangeException as err: + log.error('Range server exception: %s', err) + return []