Merge branch 'changed_when' into devel
This commit is contained in:
commit
f3c69040b4
7 changed files with 79 additions and 10 deletions
|
@ -360,7 +360,7 @@ class PlayBook(object):
|
||||||
# extra vars need to always trump - so update again following the facts
|
# extra vars need to always trump - so update again following the facts
|
||||||
self.SETUP_CACHE[host].update(self.extra_vars)
|
self.SETUP_CACHE[host].update(self.extra_vars)
|
||||||
if task.register:
|
if task.register:
|
||||||
if 'stdout' in result:
|
if 'stdout' in result and 'stdout_lines' not in result:
|
||||||
result['stdout_lines'] = result['stdout'].splitlines()
|
result['stdout_lines'] = result['stdout'].splitlines()
|
||||||
self.SETUP_CACHE[host][task.register] = result
|
self.SETUP_CACHE[host][task.register] = result
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ class PlayBook(object):
|
||||||
if task.ignore_errors and task.register:
|
if task.ignore_errors and task.register:
|
||||||
failed = results.get('failed', {})
|
failed = results.get('failed', {})
|
||||||
for host, result in failed.iteritems():
|
for host, result in failed.iteritems():
|
||||||
if 'stdout' in result:
|
if 'stdout' in result and 'stdout_lines' not in result:
|
||||||
result['stdout_lines'] = result['stdout'].splitlines()
|
result['stdout_lines'] = result['stdout'].splitlines()
|
||||||
self.SETUP_CACHE[host][task.register] = result
|
self.SETUP_CACHE[host][task.register] = result
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Task(object):
|
||||||
'delegate_to', 'first_available_file', 'ignore_errors',
|
'delegate_to', 'first_available_file', 'ignore_errors',
|
||||||
'local_action', 'transport', 'sudo', 'sudo_user', 'sudo_pass',
|
'local_action', 'transport', 'sudo', 'sudo_user', 'sudo_pass',
|
||||||
'items_lookup_plugin', 'items_lookup_terms', 'environment', 'args',
|
'items_lookup_plugin', 'items_lookup_terms', 'environment', 'args',
|
||||||
'any_errors_fatal'
|
'any_errors_fatal', 'changed_when'
|
||||||
]
|
]
|
||||||
|
|
||||||
# to prevent typos and such
|
# to prevent typos and such
|
||||||
|
@ -38,7 +38,7 @@ class Task(object):
|
||||||
'first_available_file', 'include', 'tags', 'register', 'ignore_errors',
|
'first_available_file', 'include', 'tags', 'register', 'ignore_errors',
|
||||||
'delegate_to', 'local_action', 'transport', 'sudo', 'sudo_user',
|
'delegate_to', 'local_action', 'transport', 'sudo', 'sudo_user',
|
||||||
'sudo_pass', 'when', 'connection', 'environment', 'args',
|
'sudo_pass', 'when', 'connection', 'environment', 'args',
|
||||||
'any_errors_fatal'
|
'any_errors_fatal', 'changed_when'
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, play, ds, module_vars=None, additional_conditions=None):
|
def __init__(self, play, ds, module_vars=None, additional_conditions=None):
|
||||||
|
@ -88,8 +88,8 @@ class Task(object):
|
||||||
else:
|
else:
|
||||||
raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
|
raise errors.AnsibleError("cannot find lookup plugin named %s for usage in with_%s" % (plugin_name, plugin_name))
|
||||||
|
|
||||||
elif x == 'when':
|
elif x in [ 'changed_when', 'when']:
|
||||||
ds['when'] = "jinja2_compare %s" % (ds[x])
|
ds[x] = "jinja2_compare %s" % (ds[x])
|
||||||
elif x.startswith("when_"):
|
elif x.startswith("when_"):
|
||||||
if 'when' in ds:
|
if 'when' in ds:
|
||||||
raise errors.AnsibleError("multiple when_* statements specified in task %s" % (ds.get('name', ds['action'])))
|
raise errors.AnsibleError("multiple when_* statements specified in task %s" % (ds.get('name', ds['action'])))
|
||||||
|
@ -161,6 +161,10 @@ class Task(object):
|
||||||
# load various attributes
|
# load various attributes
|
||||||
self.only_if = ds.get('only_if', 'True')
|
self.only_if = ds.get('only_if', 'True')
|
||||||
self.when = ds.get('when', None)
|
self.when = ds.get('when', None)
|
||||||
|
self.changed_when = ds.get('changed_when', None)
|
||||||
|
|
||||||
|
if self.changed_when is not None:
|
||||||
|
self.changed_when = utils.compile_when_to_only_if(self.changed_when)
|
||||||
|
|
||||||
self.async_seconds = int(ds.get('async', 0)) # not async by default
|
self.async_seconds = int(ds.get('async', 0)) # not async by default
|
||||||
self.async_poll_interval = int(ds.get('poll', 10)) # default poll = 10 seconds
|
self.async_poll_interval = int(ds.get('poll', 10)) # default poll = 10 seconds
|
||||||
|
@ -214,6 +218,8 @@ class Task(object):
|
||||||
|
|
||||||
# make ignore_errors accessable to Runner code
|
# make ignore_errors accessable to Runner code
|
||||||
self.module_vars['ignore_errors'] = self.ignore_errors
|
self.module_vars['ignore_errors'] = self.ignore_errors
|
||||||
|
self.module_vars['register'] = self.register
|
||||||
|
self.module_vars['changed_when'] = self.changed_when
|
||||||
|
|
||||||
# tags allow certain parts of a playbook to be run without running the whole playbook
|
# tags allow certain parts of a playbook to be run without running the whole playbook
|
||||||
apply_tags = ds.get('tags', None)
|
apply_tags = ds.get('tags', None)
|
||||||
|
|
|
@ -528,7 +528,8 @@ class Runner(object):
|
||||||
self.conditional = [ self.conditional ]
|
self.conditional = [ self.conditional ]
|
||||||
|
|
||||||
for cond in self.conditional:
|
for cond in self.conditional:
|
||||||
if not utils.check_conditional(cond, self.basedir, inject):
|
|
||||||
|
if not utils.check_conditional(cond, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars):
|
||||||
result = utils.jsonify(dict(changed=False, skipped=True))
|
result = utils.jsonify(dict(changed=False, skipped=True))
|
||||||
self.callbacks.on_skipped(host, inject.get('item',None))
|
self.callbacks.on_skipped(host, inject.get('item',None))
|
||||||
return ReturnData(host=host, result=result)
|
return ReturnData(host=host, result=result)
|
||||||
|
@ -629,6 +630,15 @@ class Runner(object):
|
||||||
module_name=module_name
|
module_name=module_name
|
||||||
)
|
)
|
||||||
|
|
||||||
|
changed_when = self.module_vars.get('changed_when')
|
||||||
|
if changed_when is not None:
|
||||||
|
register = self.module_vars.get('register')
|
||||||
|
if register is not None:
|
||||||
|
if 'stdout' in data:
|
||||||
|
data['stdout_lines'] = data['stdout'].splitlines()
|
||||||
|
inject[register] = data
|
||||||
|
data['changed'] = utils.check_conditional(changed_when, self.basedir, inject, fail_on_undefined=self.error_on_undefined_vars)
|
||||||
|
|
||||||
if is_chained:
|
if is_chained:
|
||||||
# no callbacks
|
# no callbacks
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -58,7 +58,7 @@ class ActionModule(object):
|
||||||
data = {}
|
data = {}
|
||||||
data.update(inject)
|
data.update(inject)
|
||||||
data.update(inject['hostvars'][host])
|
data.update(inject['hostvars'][host])
|
||||||
if not check_conditional(self.runner.basedir, self.runner.conditional, data):
|
if not check_conditional(self.runner.basedir, self.runner.conditional, data, fail_on_undefined=self.runner.error_on_undefined_vars):
|
||||||
continue
|
continue
|
||||||
group_name = template.template(self.runner.basedir, args['key'], data)
|
group_name = template.template(self.runner.basedir, args['key'], data)
|
||||||
group_name = group_name.replace(' ','-')
|
group_name = group_name.replace(' ','-')
|
||||||
|
|
|
@ -155,14 +155,14 @@ def is_changed(result):
|
||||||
|
|
||||||
return (result.get('changed', False) in [ True, 'True', 'true'])
|
return (result.get('changed', False) in [ True, 'True', 'true'])
|
||||||
|
|
||||||
def check_conditional(conditional, basedir, inject):
|
def check_conditional(conditional, basedir, inject, fail_on_undefined=False):
|
||||||
|
|
||||||
if conditional.startswith("jinja2_compare"):
|
if conditional.startswith("jinja2_compare"):
|
||||||
conditional = conditional.replace("jinja2_compare ","")
|
conditional = conditional.replace("jinja2_compare ","")
|
||||||
# allow variable names
|
# allow variable names
|
||||||
if conditional in inject:
|
if conditional in inject:
|
||||||
conditional = inject[conditional]
|
conditional = inject[conditional]
|
||||||
conditional = template.template(basedir, conditional, inject)
|
conditional = template.template(basedir, conditional, inject, fail_on_undefined=fail_on_undefined)
|
||||||
# a Jinja2 evaluation that results in something Python can eval!
|
# a Jinja2 evaluation that results in something Python can eval!
|
||||||
presented = "{% if " + conditional + " %} True {% else %} False {% endif %}"
|
presented = "{% if " + conditional + " %} True {% else %} False {% endif %}"
|
||||||
conditional = template.template(basedir, presented, inject)
|
conditional = template.template(basedir, presented, inject)
|
||||||
|
|
|
@ -407,6 +407,34 @@ class TestPlaybook(unittest.TestCase):
|
||||||
|
|
||||||
assert utils.jsonify(expected, format=True) == utils.jsonify(actual,format=True)
|
assert utils.jsonify(expected, format=True) == utils.jsonify(actual,format=True)
|
||||||
|
|
||||||
|
def test_playbook_changed_when(self):
|
||||||
|
test_callbacks = TestCallbacks()
|
||||||
|
playbook = ansible.playbook.PlayBook(
|
||||||
|
playbook=os.path.join(self.test_dir, 'playbook-changed_when.yml'),
|
||||||
|
host_list='test/ansible_hosts',
|
||||||
|
stats=ans_callbacks.AggregateStats(),
|
||||||
|
callbacks=test_callbacks,
|
||||||
|
runner_callbacks=test_callbacks
|
||||||
|
)
|
||||||
|
actual = playbook.run()
|
||||||
|
|
||||||
|
# if different, this will output to screen
|
||||||
|
print "**ACTUAL**"
|
||||||
|
print utils.jsonify(actual, format=True)
|
||||||
|
expected = {
|
||||||
|
"localhost": {
|
||||||
|
"changed": 3,
|
||||||
|
"failures": 0,
|
||||||
|
"ok": 6,
|
||||||
|
"skipped": 0,
|
||||||
|
"unreachable": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "**EXPECTED**"
|
||||||
|
print utils.jsonify(expected, format=True)
|
||||||
|
|
||||||
|
assert utils.jsonify(expected, format=True) == utils.jsonify(actual,format=True)
|
||||||
|
|
||||||
def _compare_file_output(self, filename, expected_lines):
|
def _compare_file_output(self, filename, expected_lines):
|
||||||
actual_lines = []
|
actual_lines = []
|
||||||
with open(filename) as f:
|
with open(filename) as f:
|
||||||
|
|
25
test/playbook-changed_when.yml
Normal file
25
test/playbook-changed_when.yml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
- hosts: all
|
||||||
|
connection: local
|
||||||
|
gather_facts: False
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- action: command echo first action
|
||||||
|
- action: command echo second action
|
||||||
|
register: var
|
||||||
|
changed_when: "'X' in var.stdout"
|
||||||
|
- action: shell exit 2
|
||||||
|
register: exit
|
||||||
|
ignore_errors: yes
|
||||||
|
changed_when: "exit.rc < 1"
|
||||||
|
- action: command echo third action
|
||||||
|
changed_when: false
|
||||||
|
- action: file path=/ state=directory
|
||||||
|
changed_when: true
|
||||||
|
- action: command echo {{item}}
|
||||||
|
register: out
|
||||||
|
changed_when: "'e' in out.stdout"
|
||||||
|
with_items:
|
||||||
|
- hello
|
||||||
|
- foo
|
||||||
|
- bye
|
Loading…
Reference in a new issue