added new 'order' directive to sort hosts in play

fixes #10964
This commit is contained in:
Brian Coca 2017-03-10 19:13:17 -05:00 committed by Brian Coca
parent 6e56a61535
commit 6b46cc5c73
5 changed files with 29 additions and 6 deletions

View file

@ -221,7 +221,7 @@ class Inventory(object):
results.append(item)
return results
def get_hosts(self, pattern="all", ignore_limits=False, ignore_restrictions=False):
def get_hosts(self, pattern="all", ignore_limits=False, ignore_restrictions=False, order=None):
"""
Takes a pattern or list of patterns and returns a list of matching
inventory host names, taking into account any active restrictions
@ -258,7 +258,21 @@ class Inventory(object):
seen = set()
HOSTS_PATTERNS_CACHE[pattern_hash] = [x for x in hosts if x not in seen and not seen.add(x)]
return HOSTS_PATTERNS_CACHE[pattern_hash][:]
# sort hosts list if needed (should only happen when called from strategy)
if order in ['sorted', 'reverse_sorted']:
from operator import attrgetter
hosts = sorted(HOSTS_PATTERNS_CACHE[pattern_hash][:], key=attrgetter('name'), reverse=(order == 'reverse_sorted'))
elif order == 'reverse_inventory':
hosts = sorted(HOSTS_PATTERNS_CACHE[pattern_hash][:], reverse=True)
else:
hosts = HOSTS_PATTERNS_CACHE[pattern_hash][:]
if order == 'shuffle':
from random import shuffle
shuffle(hosts)
elif order not in [None, 'inventory']:
AnsibleError("Invalid 'order' specified for inventory hosts: %s" % order)
return hosts
@classmethod
def split_host_pattern(cls, pattern):

View file

@ -56,7 +56,7 @@ class Play(Base, Taggable, Become):
"""
# =================================================================================
# Connection-Related Attributes
_name = FieldAttribute(isa='string', default='', always_post_validate=True)
# TODO: generalize connection
_accelerate = FieldAttribute(isa='bool', default=False, always_post_validate=True)
@ -69,7 +69,6 @@ class Play(Base, Taggable, Become):
_gather_subset = FieldAttribute(isa='barelist', default=None, always_post_validate=True)
_gather_timeout = FieldAttribute(isa='int', default=None, always_post_validate=True)
_hosts = FieldAttribute(isa='list', required=True, listof=string_types, always_post_validate=True)
_name = FieldAttribute(isa='string', default='', always_post_validate=True)
# Variable Attributes
_vars_files = FieldAttribute(isa='list', default=[], priority=99)
@ -90,6 +89,7 @@ class Play(Base, Taggable, Become):
_max_fail_percentage = FieldAttribute(isa='percent', always_post_validate=True)
_serial = FieldAttribute(isa='list', default=[], always_post_validate=True)
_strategy = FieldAttribute(isa='string', default=C.DEFAULT_STRATEGY, always_post_validate=True)
_order = FieldAttribute(isa='string', always_post_validate=True)
# =================================================================================

View file

@ -918,3 +918,11 @@ class StrategyBase:
display.vv("META: %s" % msg)
return [TaskResult(target_host, task, result)]
def get_hosts_left(self, iterator):
hosts_left = []
for host in self._inventory.get_hosts(iterator._play.hosts, order=iterator._play.order):
if host.name not in self._tqm._unreachable_hosts:
hosts_left.append(host)
return hosts_left

View file

@ -61,7 +61,8 @@ class StrategyModule(StrategyBase):
work_to_do = True
while work_to_do and not self._tqm._terminated:
hosts_left = [host for host in self._inventory.get_hosts(iterator._play.hosts) if host.name not in self._tqm._unreachable_hosts]
hosts_left = self.get_hosts_left(iterator)
if len(hosts_left) == 0:
self._tqm.send_callback('v2_playbook_on_no_hosts_remaining')
result = False

View file

@ -167,7 +167,7 @@ class StrategyModule(StrategyBase):
try:
display.debug("getting the remaining hosts for this loop")
hosts_left = [host for host in self._inventory.get_hosts(iterator._play.hosts) if host.name not in self._tqm._unreachable_hosts]
hosts_left = self.get_hosts_left(iterator)
display.debug("done getting the remaining hosts for this loop")
# queue up this task for each host in the inventory