diff --git a/lib/ansible/callbacks.py b/lib/ansible/callbacks.py index ce06af6609..2a49316122 100644 --- a/lib/ansible/callbacks.py +++ b/lib/ansible/callbacks.py @@ -259,7 +259,7 @@ class PlaybookRunnerCallbacks(DefaultRunnerCallbacks): else: print "fatal: [%s] => %s" % (host, msg) - def on_failed(self, host, results): + def on_failed(self, host, results, ignore_errors): item = results.get('item', None) @@ -269,6 +269,8 @@ class PlaybookRunnerCallbacks(DefaultRunnerCallbacks): msg = "failed: [%s] => %s" % (host, utils.jsonify(results)) print stringc(msg, 'red') + if ignore_errors: + print stringc("...ignoring", 'yellow') def on_ok(self, host, host_result): diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py index c1ff016c68..1cdf450cde 100644 --- a/lib/ansible/playbook/task.py +++ b/lib/ansible/playbook/task.py @@ -23,13 +23,13 @@ class Task(object): __slots__ = [ 'name', 'action', 'only_if', 'async_seconds', 'async_poll_interval', 'notify', 'module_name', 'module_args', 'module_vars', - 'play', 'notified_by', 'tags', 'with_items', 'first_available_file' + 'play', 'notified_by', 'tags', 'with_items', 'first_available_file', 'ignore_errors' ] # to prevent typos and such VALID_KEYS = [ 'name', 'action', 'only_if', 'async', 'poll', 'notify', 'with_items', 'first_available_file', - 'include', 'tags' + 'include', 'tags', 'ignore_errors' ] def __init__(self, play, ds, module_vars=None): @@ -62,7 +62,8 @@ class Task(object): self.notify = ds.get('notify', []) self.first_available_file = ds.get('first_available_file', None) self.with_items = ds.get('with_items', None) - + self.ignore_errors = ds.get('ignore_errors', False) + # notify can be a string or a list, store as a list if isinstance(self.notify, basestring): self.notify = [ self.notify ] @@ -97,6 +98,9 @@ class Task(object): self.with_items = [ ] self.module_vars['items'] = self.with_items + # make ignore_errors accessable to Runner code + self.module_vars['ignore_errors'] = self.ignore_errors + # tags allow certain parts of a playbook to be run without running the whole playbook apply_tags = ds.get('tags', None) if apply_tags is not None: diff --git a/lib/ansible/runner/__init__.py b/lib/ansible/runner/__init__.py index 4468f107c1..351bbf977a 100644 --- a/lib/ansible/runner/__init__.py +++ b/lib/ansible/runner/__init__.py @@ -602,7 +602,13 @@ class Runner(object): if 'skipped' in data: self.callbacks.on_skipped(result.host) elif not result.is_successful(): - self.callbacks.on_failed(result.host, data) + ignore_errors = self.module_vars['ignore_errors'] + self.callbacks.on_failed(result.host, data, ignore_errors) + if ignore_errors: + if 'failed' in result.result: + result.result['failed'] = False + if 'rc' in result.result: + result.result['rc'] = 0 else: self.callbacks.on_ok(result.host, data) return result