diff --git a/docsite/rst/playbooks_checkmode.rst b/docsite/rst/playbooks_checkmode.rst index 6cf677057f..954da5249e 100644 --- a/docsite/rst/playbooks_checkmode.rst +++ b/docsite/rst/playbooks_checkmode.rst @@ -20,31 +20,50 @@ Example:: .. _forcing_to_run_in_check_mode: -Running a task in check mode -```````````````````````````` +Enabling or disabling check mode for tasks +`````````````````````````````````````````` -.. versionadded:: 1.3 +.. versionadded:: 2.2 -Sometimes you may want to have a task to be executed even in check -mode. To achieve this, use the `always_run` clause on the task. Its -value is a Jinja2 expression, just like the `when` clause. In simple -cases a boolean YAML value would be sufficient as a value. +Sometimes you may want to modify the check mode behavior of individual tasks. This is done via the ``check_mode`` option, which can +be added to tasks. + +There are two options: + +1. Force a task to **run in check mode**, even when the playbook is called **without** ``--check``. This is called ``check_mode: yes``. +2. Force a task to **run in normal mode** and make changes to the system, even when the playbook is called **with** ``--check``. This is called ``check_mode: no``. + +.. note:: Prior to version 2.2 only the the equivalent of ``check_mode: no`` existed. The notation for that was ``always_run: yes``. + +Instead of ``yes``/``no`` you can use a Jinja2 expression, just like the ``when`` clause. Example:: tasks: - - name: this task is run even in check mode + - name: this task will make changes to the system even in check mode command: /something/to/run --even-in-check-mode - always_run: yes + check_mode: no -As a reminder, a task with a `when` clause evaluated to false, will -still be skipped even if it has a `always_run` clause evaluated to -true. + - name: this task will always run under checkmode and not change the system + lineinfile: line="important config" dest=/path/to/myconfig.conf state=present + check_mode: yes -Also if you want to skip, or ignore errors on some tasks in check mode -you can use a boolean magic variable `ansible_check_mode` (added in version 2.1) -which will be set to `True` during check mode. + +Running single tasks with ``check_mode: yes`` can be useful to write tests for +ansible modules, either to test the module itself or to the the conditions under +which a module would make changes. +With ``register`` (see :doc:`playbooks_conditionals`) you can check the +potential changes. + +Information about check mode in variables +````````````````````````````````````````` + +.. versionadded:: 2.1 + +If you want to skip, or ignore errors on some tasks in check mode +you can use a boolean magic variable ``ansible_check_mode`` +which will be set to ``True`` during check mode. Example:: diff --git a/docsite/rst/test_strategies.rst b/docsite/rst/test_strategies.rst index edca8ea2d8..f11eb98f18 100644 --- a/docsite/rst/test_strategies.rst +++ b/docsite/rst/test_strategies.rst @@ -42,7 +42,7 @@ existing system, using the `--check` flag to the `ansible` command will report i bring the system into a desired state. This can let you know up front if there is any need to deploy onto the given system. Ordinarily scripts and commands don't run in check mode, so if you -want certain steps to always execute in check mode, such as calls to the script module, add the 'always_run' flag:: +want certain steps to always execute in check mode, such as calls to the script module, disable check mode for those tasks:: roles: @@ -50,7 +50,7 @@ want certain steps to always execute in check mode, such as calls to the script tasks: - script: verify.sh - always_run: True + check_mode: no Modules That Are Useful for Testing ``````````````````````````````````` diff --git a/lib/ansible/playbook/base.py b/lib/ansible/playbook/base.py index e3ae6374ae..6bafe42844 100644 --- a/lib/ansible/playbook/base.py +++ b/lib/ansible/playbook/base.py @@ -63,6 +63,7 @@ class Base: _always_run = FieldAttribute(isa='bool') _run_once = FieldAttribute(isa='bool') _ignore_errors = FieldAttribute(isa='bool') + _check_mode = FieldAttribute(isa='bool') # param names which have been deprecated/removed DEPRECATED_ATTRIBUTES = [ diff --git a/lib/ansible/playbook/play_context.py b/lib/ansible/playbook/play_context.py index 463144c85c..559f0343d2 100644 --- a/lib/ansible/playbook/play_context.py +++ b/lib/ansible/playbook/play_context.py @@ -440,10 +440,15 @@ class PlayContext(Base): # set become defaults if not previouslly set task.set_become_defaults(new_info.become, new_info.become_method, new_info.become_user) - # have always_run override check mode if task.always_run: + display.deprecated("always_run is deprecated. Use check_mode = no instead.", version="2.4", removed=False) new_info.check_mode = False + # check_mode replaces always_run, overwrite always_run if both are given + if task.check_mode is not None: + new_info.check_mode = task.check_mode + + return new_info def make_become_cmd(self, cmd, executable=None): diff --git a/test/integration/roles/test_always_run/tasks/main.yml b/test/integration/roles/test_always_run/tasks/main.yml index 036a6b9860..eb27785ad6 100644 --- a/test/integration/roles/test_always_run/tasks/main.yml +++ b/test/integration/roles/test_always_run/tasks/main.yml @@ -18,7 +18,7 @@ - name: run a command while in check mode shell: echo "running" - always_run: yes + check_mode: no register: result - name: assert that the command was run diff --git a/test/integration/roles/test_check_mode/tasks/main.yml b/test/integration/roles/test_check_mode/tasks/main.yml index d8edf5b285..e7dd6f532f 100644 --- a/test/integration/roles/test_check_mode/tasks/main.yml +++ b/test/integration/roles/test_check_mode/tasks/main.yml @@ -17,23 +17,30 @@ # along with Ansible. If not, see . - name: fill in a basic template in check mode - template: src=foo.j2 dest={{output_dir}}/foo.templated mode=0644 + template: src=foo.j2 dest={{output_dir}}/checkmode_foo.templated mode=0644 register: template_result +- name: check whether file exists + stat: path={{output_dir}}/checkmode_foo.templated + register: foo + - name: verify that the file was marked as changed in check mode assert: that: - - "template_result.changed == true" + - "template_result|changed" + - "not foo.stat.exists" -- name: Actually create the file - template: src=foo.j2 dest={{output_dir}}/foo.templated2 mode=0644 - always_run: True +- name: Actually create the file, disable check mode + template: src=foo.j2 dest={{output_dir}}/checkmode_foo.templated2 mode=0644 + check_mode: no + register: checkmode_disabled -- name: fill in a basic template in check mode - template: src=foo.j2 dest={{output_dir}}/foo.templated2 mode=0644 +- name: fill in template with new content + template: src=foo.j2 dest={{output_dir}}/checkmode_foo.templated2 mode=0644 register: template_result2 -- name: verify that the file was marked as not changed in check mode +- name: verify that the file was not changed assert: that: - - "template_result2.changed == false" + - "checkmode_disabled|changed" + - "not template_result2|changed" diff --git a/test/integration/roles/test_template/tasks/main.yml b/test/integration/roles/test_template/tasks/main.yml index 9fd1d860e0..56d156eb75 100644 --- a/test/integration/roles/test_template/tasks/main.yml +++ b/test/integration/roles/test_template/tasks/main.yml @@ -179,3 +179,49 @@ that: - "template_result.changed == False" + +# check_mode + +- name: fill in a basic template in check mode + template: src=short.j2 dest={{output_dir}}/short.templated + register: template_result + check_mode: True + +- name: check file exists + stat: path={{output_dir}}/short.templated + register: templated + +- name: verify that the file was marked as changed in check mode but was not created + assert: + that: + - "not templated.stat.exists" + - "template_result|changed" + +- name: fill in a basic template + template: src=short.j2 dest={{output_dir}}/short.templated + +- name: fill in a basic template in check mode + template: src=short.j2 dest={{output_dir}}/short.templated + register: template_result + check_mode: True + +- name: verify that the file was marked as not changes in check mode + assert: + that: + - "not template_result|changed" + - "'templated_var_loaded' in lookup('file', '{{output_dir | expanduser}}/short.templated')" + +- name: change var for the template + set_fact: + templated_var: "changed" + +- name: fill in a basic template with changed var in check mode + template: src=short.j2 dest={{output_dir}}/short.templated + register: template_result + check_mode: True + +- name: verify that the file was marked as changed in check mode but the content was not changed + assert: + that: + - "'templated_var_loaded' in lookup('file', '{{output_dir | expanduser }}/short.templated')" + - "template_result|changed" diff --git a/test/integration/roles/test_template/templates/short.j2 b/test/integration/roles/test_template/templates/short.j2 new file mode 100644 index 0000000000..55aab8f1ea --- /dev/null +++ b/test/integration/roles/test_template/templates/short.j2 @@ -0,0 +1 @@ +{{ templated_var }}