From eed6cf5dadc5e64353635506be82ba8e983cd20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Strahinja=20Kustudi=C4=87?= Date: Wed, 20 Jan 2016 19:47:09 +0100 Subject: [PATCH] Adds 'ansible_check_mode' boolean magic variable * Makes it possible to pass any options variable to VariableManager by changing `load_options_vars(options)` in `lib/ansible/utils/vars.py` --- docsite/rst/playbooks_checkmode.rst | 20 +++++++++++++++++++- docsite/rst/playbooks_variables.rst | 4 +++- lib/ansible/cli/adhoc.py | 3 +++ lib/ansible/cli/playbook.py | 3 +++ lib/ansible/utils/vars.py | 7 +++++++ lib/ansible/vars/__init__.py | 17 +++++++++++++++++ test/units/vars/test_variable_manager.py | 2 ++ 7 files changed, 54 insertions(+), 2 deletions(-) diff --git a/docsite/rst/playbooks_checkmode.rst b/docsite/rst/playbooks_checkmode.rst index 77bae8df4d..18d7b0cd60 100644 --- a/docsite/rst/playbooks_checkmode.rst +++ b/docsite/rst/playbooks_checkmode.rst @@ -38,7 +38,25 @@ Example:: 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. +true. + +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. + +Example:: + + tasks: + + - name: this task will be skipped in check mode + git: repo=ssh://git@github.com/mylogin/hello.git dest=/home/mylogin/hello + when: not ansible_check_mode + + - name: this task will ignore errors in check mode + git: repo=ssh://git@github.com/mylogin/hello.git dest=/home/mylogin/hello + ignore_errors: "{{ ansible_check_mode }}" + + .. _diff_mode: diff --git a/docsite/rst/playbooks_variables.rst b/docsite/rst/playbooks_variables.rst index bcdcaad331..89d379c3c4 100644 --- a/docsite/rst/playbooks_variables.rst +++ b/docsite/rst/playbooks_variables.rst @@ -674,7 +674,9 @@ Don't worry about any of this unless you think you need it. You'll know when yo Also available, ``inventory_dir`` is the pathname of the directory holding Ansible's inventory host file, ``inventory_file`` is the pathname and the filename pointing to the Ansible's inventory host file. -And finally, ``role_path`` will return the current role's pathname (since 1.8). This will only work inside a role. +We then have ``role_path`` which will return the current role's pathname (since 1.8). This will only work inside a role. + +And finally, ``ansible_check_mode`` (added in version 2.1), a boolean magic variable which will be set to ``True`` if you run Ansible with ``--check``. .. _variable_file_separation_details: diff --git a/lib/ansible/cli/adhoc.py b/lib/ansible/cli/adhoc.py index d7fc5d7fad..c1a23f6c25 100644 --- a/lib/ansible/cli/adhoc.py +++ b/lib/ansible/cli/adhoc.py @@ -32,6 +32,7 @@ from ansible.parsing.splitter import parse_kv from ansible.playbook.play import Play from ansible.plugins import get_all_plugin_loaders from ansible.utils.vars import load_extra_vars +from ansible.utils.vars import load_options_vars from ansible.utils.unicode import to_unicode from ansible.vars import VariableManager @@ -123,6 +124,8 @@ class AdHocCLI(CLI): variable_manager = VariableManager() variable_manager.extra_vars = load_extra_vars(loader=loader, options=self.options) + variable_manager.options_vars = load_options_vars(self.options) + inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=self.options.inventory) variable_manager.set_inventory(inventory) diff --git a/lib/ansible/cli/playbook.py b/lib/ansible/cli/playbook.py index ff0255e653..ec3a91776e 100644 --- a/lib/ansible/cli/playbook.py +++ b/lib/ansible/cli/playbook.py @@ -33,6 +33,7 @@ from ansible.parsing.dataloader import DataLoader from ansible.playbook.block import Block from ansible.playbook.play_context import PlayContext from ansible.utils.vars import load_extra_vars +from ansible.utils.vars import load_options_vars from ansible.vars import VariableManager try: @@ -125,6 +126,8 @@ class PlaybookCLI(CLI): variable_manager = VariableManager() variable_manager.extra_vars = load_extra_vars(loader=loader, options=self.options) + variable_manager.options_vars = load_options_vars(self.options) + # create the inventory, and filter it based on the subset specified (if any) inventory = Inventory(loader=loader, variable_manager=variable_manager, host_list=self.options.inventory) variable_manager.set_inventory(inventory) diff --git a/lib/ansible/utils/vars.py b/lib/ansible/utils/vars.py index 01eb5ac821..ee3dd5feaa 100644 --- a/lib/ansible/utils/vars.py +++ b/lib/ansible/utils/vars.py @@ -111,6 +111,13 @@ def load_extra_vars(loader, options): extra_vars = combine_vars(extra_vars, data) return extra_vars +def load_options_vars(options): + options_vars = {} + # For now only return check mode, but we can easily return more + # options if we need variables for them + options_vars['ansible_check_mode'] = options.check + return options_vars + def isidentifier(ident): """ Determines, if string is valid Python identifier using the ast module. diff --git a/lib/ansible/vars/__init__.py b/lib/ansible/vars/__init__.py index b87514cdf6..22fa2e3f46 100644 --- a/lib/ansible/vars/__init__.py +++ b/lib/ansible/vars/__init__.py @@ -99,6 +99,7 @@ class VariableManager: self._inventory = None self._hostvars = None self._omit_token = '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest() + self._options_vars = defaultdict(dict) def __getstate__(self): data = dict( @@ -109,6 +110,7 @@ class VariableManager: host_vars_files = self._host_vars_files, group_vars_files = self._group_vars_files, omit_token = self._omit_token, + options_vars = self._options_vars, #inventory = self._inventory, ) return data @@ -122,6 +124,7 @@ class VariableManager: self._group_vars_files = data.get('group_vars_files', defaultdict(dict)) self._omit_token = data.get('omit_token', '__omit_place_holder__%s' % sha1(os.urandom(64)).hexdigest()) self._inventory = data.get('inventory', None) + self._options_vars = data.get('options_vars', dict()) def _get_cache_entry(self, play=None, host=None, task=None): play_id = "NONE" @@ -152,6 +155,17 @@ class VariableManager: def set_inventory(self, inventory): self._inventory = inventory + @property + def options_vars(self): + ''' ensures a clean copy of the options_vars are made ''' + return self._options_vars.copy() + + @options_vars.setter + def options_vars(self, value): + ''' ensures a clean copy of the options_vars are used to set the value ''' + assert isinstance(value, dict) + self._options_vars = value.copy() + def _preprocess_vars(self, a): ''' Ensures that vars contained in the parameter passed in are @@ -392,6 +406,9 @@ class VariableManager: # the 'omit' value alows params to be left out if the variable they are based on is undefined variables['omit'] = self._omit_token variables['ansible_version'] = CLI.version_info(gitinfo=False) + # Set options vars + for option, option_value in self._options_vars.iteritems(): + variables[option] = option_value if self._hostvars is not None and include_hostvars: variables['hostvars'] = self._hostvars diff --git a/test/units/vars/test_variable_manager.py b/test/units/vars/test_variable_manager.py index 41f08138a5..91cb5b3f7f 100644 --- a/test/units/vars/test_variable_manager.py +++ b/test/units/vars/test_variable_manager.py @@ -49,6 +49,8 @@ class TestVariableManager(unittest.TestCase): del vars['vars'] if 'ansible_version' in vars: del vars['ansible_version'] + if 'ansible_check_mode' in vars: + del vars['ansible_check_mode'] self.assertEqual(vars, dict(playbook_dir='.'))