mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Notifable handlers only run when something is changed. Awesome.
This commit is contained in:
parent
de80166b6d
commit
79fdc1b6f4
3 changed files with 46 additions and 65 deletions
36
TODO.md
36
TODO.md
|
@ -1,36 +0,0 @@
|
|||
TODO list and plans
|
||||
===================
|
||||
|
||||
Playbook TODO:
|
||||
|
||||
* error codes and failure summaries
|
||||
* handle 'changed' attributes
|
||||
* fail nodes on errors, i.e. remove from host list, rather than continuing to pound them
|
||||
* further improve output
|
||||
* more conditional capability (if statement) (?)
|
||||
* very good logging
|
||||
|
||||
Command module:
|
||||
* magic to pull async & timeout options off of the command line and not feed them
|
||||
to the app we're executing
|
||||
|
||||
General:
|
||||
|
||||
* better logging
|
||||
* async options
|
||||
* modules for users, groups, and files, using puppet style ensure mechanics
|
||||
* think about how to build idempotency (aka Puppet-style 'creates') around command module?
|
||||
|
||||
Bonus utilities:
|
||||
|
||||
* ansible-inventory - gathering fact/hw info, storing in git, adding RSS
|
||||
* ansible-slurp - recursively rsync file trees for each host
|
||||
* maybe it's own fact engine, not required, that also feeds from facter
|
||||
|
||||
Not so interested really, but maybe:
|
||||
|
||||
* list available modules from command line
|
||||
* add/remove/list hosts from the command line
|
||||
* filter exclusion (run this only if fact is true/false)
|
||||
-- should be doable with playbooks (i.e. not neccessary)
|
||||
|
|
@ -6,17 +6,18 @@
|
|||
- do:
|
||||
- copy a file
|
||||
- copy /srv/a /srv/b
|
||||
notify:
|
||||
- restart apache
|
||||
- do:
|
||||
- template from local file template.j2 to remote location /srv/file.out
|
||||
- template /srv/template.j2 /srv/file.out
|
||||
- do:
|
||||
- update apache
|
||||
- command /usr/bin/yum update apache
|
||||
onchange:
|
||||
notify:
|
||||
- restart apache
|
||||
- quack like a duck
|
||||
handlers:
|
||||
- do:
|
||||
- restart apache
|
||||
- command /sbin/service apache restart
|
||||
- command /sbin/service httpd restart
|
||||
- do:
|
||||
- run bin false
|
||||
- command /bin/false
|
||||
|
||||
- quack like a duck
|
||||
- command /bin/true
|
||||
|
|
|
@ -101,7 +101,7 @@ class PlayBook(object):
|
|||
timeout=self.timeout
|
||||
)
|
||||
|
||||
def _run_task(self, pattern, task, host_list=None, conditional=False):
|
||||
def _run_task(self, pattern=None, task=None, host_list=None, handlers=None, conditional=False):
|
||||
'''
|
||||
run a single task in the playbook and
|
||||
recursively run any subtasks.
|
||||
|
@ -118,7 +118,7 @@ class PlayBook(object):
|
|||
|
||||
namestr = "%s/%s" % (pattern, comment)
|
||||
if conditional:
|
||||
namestr = "subset/%s" % namestr
|
||||
namestr = "notified/%s" % namestr
|
||||
print "TASK [%s]" % namestr
|
||||
|
||||
runner = self._get_task_runner(
|
||||
|
@ -130,15 +130,7 @@ class PlayBook(object):
|
|||
results = runner.run()
|
||||
|
||||
dark = results.get("dark", [])
|
||||
|
||||
contacted = results.get("contacted", [])
|
||||
|
||||
# TODO: filter based on values that indicate
|
||||
# they have changed events to emulate Puppet
|
||||
# 'notify' behavior, super easy -- just
|
||||
# a list comprehension -- but we need complaint
|
||||
# modules first
|
||||
|
||||
ok_hosts = contacted.keys()
|
||||
|
||||
for host, msg in dark.items():
|
||||
|
@ -152,27 +144,51 @@ class PlayBook(object):
|
|||
print "FAIL: [%s/%s]" % (host, comment, results)
|
||||
|
||||
|
||||
subtasks = task.get('onchange', [])
|
||||
# flag which notify handlers need to be run
|
||||
subtasks = task.get('notify', [])
|
||||
if len(subtasks) > 0:
|
||||
for subtask in subtasks:
|
||||
self._run_task(pattern, subtask, ok_hosts, conditional=True)
|
||||
for host, results in contacted.items():
|
||||
if results.get('changed', False):
|
||||
for subtask in subtasks:
|
||||
self._flag_handler(handlers, subtask, host)
|
||||
|
||||
# TODO: if a host fails in task 1, add it to an excludes
|
||||
# list such that no other tasks in the list ever execute
|
||||
# unlike Puppet, do not allow partial failure of the tree
|
||||
# and continuing as far as possible. Fail fast.
|
||||
# TODO: if a host fails in any task, remove it from
|
||||
# the host list immediately
|
||||
|
||||
def _flag_handler(self, handlers, match_name, host):
|
||||
'''
|
||||
if a task has any notify elements, flag handlers for run
|
||||
at end of execution cycle for hosts that have indicated
|
||||
changes have been made
|
||||
'''
|
||||
for x in handlers:
|
||||
attribs = x["do"]
|
||||
name = attribs[0]
|
||||
if match_name == name:
|
||||
if not x.has_key("run"):
|
||||
x['run'] = []
|
||||
x['run'].append(host)
|
||||
|
||||
def _run_pattern(self, pg):
|
||||
'''
|
||||
run a list of tasks for a given pattern, in order
|
||||
'''
|
||||
|
||||
pattern = pg['pattern']
|
||||
tasks = pg['tasks']
|
||||
for task in tasks:
|
||||
self._run_task(pattern, task)
|
||||
pattern = pg['pattern']
|
||||
tasks = pg['tasks']
|
||||
handlers = pg['handlers']
|
||||
|
||||
for task in tasks:
|
||||
self._run_task(pattern=pattern, task=task, handlers=handlers)
|
||||
for task in handlers:
|
||||
if type(task.get("run", None)) == list:
|
||||
self._run_task(
|
||||
pattern=pattern,
|
||||
task=task,
|
||||
handlers=handlers,
|
||||
host_list=task.get('run',[]),
|
||||
conditional=True
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue