diff --git a/lib/ansible/modules/utilities/logic/include_vars.py b/lib/ansible/modules/utilities/logic/include_vars.py index 8e7f4aa1bd..2ac9dc31e3 100644 --- a/lib/ansible/modules/utilities/logic/include_vars.py +++ b/lib/ansible/modules/utilities/logic/include_vars.py @@ -18,8 +18,7 @@ author: "Allen Sanabria (@linuxdynasty)" module: include_vars short_description: Load variables from files, dynamically within a task. description: - - Loads variables from a YAML/JSON files dynamically from within a file or - from a directory recursively during task runtime. If loading a directory, the files are sorted alphabetically before being loaded. + - Loads variables from a YAML/JSON files dynamically from within a file or from a directory recursively during task runtime. If loading a directory, the files are sorted alphabetically before being loaded. version_added: "1.4" options: file: @@ -41,66 +40,78 @@ options: depth: version_added: "2.2" description: - - By default, this module will recursively go through each sub directory and load up the variables. By explicitly setting the depth, this module will only go as deep as the depth. + - When using C(dir), this module will, by default, recursively go through each sub directory and load up the variables. + By explicitly setting the depth, this module will only go as deep as the depth. default: 0 files_matching: version_added: "2.2" description: - - Limit the variables that are loaded within any directory to this regular expression. + - Limit the files that are loaded within any directory to this regular expression. default: null ignore_files: version_added: "2.2" description: - - List of file names to ignore. The defaults can not be overridden, but can be extended. + - List of file names to ignore. default: null + extensions: + version_added: "2.3" + description: + - List of file extensions to read when using C(dir). + default: ['yaml', 'yml', 'json'] + required: False free-form: description: - This module allows you to specify the 'file' option directly w/o any other options. + There is no 'free-form' option, this is just an indicator, see example below. ''' EXAMPLES = """ -# Include vars of stuff.yml into the 'stuff' variable (2.2). -- include_vars: +- name: Include vars of stuff.yml into the 'stuff' variable (2.2). + include_vars: file: stuff.yml name: stuff -# Conditionally decide to load in variables into 'plans' when x is 0, otherwise do not. (2.2) -- include_vars: +- name: Conditionally decide to load in variables into 'plans' when x is 0, otherwise do not. (2.2) + include_vars: file: contingency_plan.yml name: plans when: x == 0 -# Load a variable file based on the OS type, or a default if not found. -- include_vars: "{{ item }}" +- name: Load a variable file based on the OS type, or a default if not found. Using free-form to specify the file. + include_vars: "{{ item }}" with_first_found: - "{{ ansible_distribution }}.yml" - "{{ ansible_os_family }}.yml" - "default.yml" -# bare include (free-form) -- include_vars: myvars.yml +- name: bare include (free-form) + include_vars: myvars.yml -# Include all yml files in vars/all and all nested directories -- include_vars: +- name: Include all .json and .jsn files in vars/all and all nested directories (2.3) + include_vars: dir: 'vars/all' + extensions: + - json + - jsn -# Include all yml files in vars/all and all nested directories and save the output in test. -- include_vars: +- name: Include all default extension files in vars/all and all nested directories and save the output in test. (2.2) + include_vars: dir: 'vars/all' name: test -# Include all yml files in vars/services -- include_vars: +- name: Include default extension files in vars/services (2.2) + include_vars: dir: 'vars/services' depth: 1 -# Include only bastion.yml files -- include_vars: +- name: Include only files matching bastion.yml (2.2) + include_vars: dir: 'vars' files_matching: 'bastion.yml' -# Include only all yml files exception bastion.yml -- include_vars: +- name: Include all .yml files except bastion.yml (2.3) + include_vars: dir: 'vars' ignore_files: 'bastion.yml' + extensions: ['yml'] """ diff --git a/lib/ansible/plugins/action/include_vars.py b/lib/ansible/plugins/action/include_vars.py index 55a53b0cee..1f57e50604 100644 --- a/lib/ansible/plugins/action/include_vars.py +++ b/lib/ansible/plugins/action/include_vars.py @@ -24,11 +24,12 @@ import re from ansible.errors import AnsibleError from ansible.module_utils._text import to_native, to_text from ansible.plugins.action import ActionBase - +from ansible.compat.six import string_types class ActionModule(ActionBase): TRANSFERS_FILES = False + VALID_FILE_EXTENSIONS = ['yaml', 'yml', 'json'] def _mutually_exclusive(self): dir_arguments = [ @@ -73,7 +74,7 @@ class ActionModule(ActionBase): """ Set instance variables based on the arguments that were passed """ self.VALID_DIR_ARGUMENTS = [ - 'dir', 'depth', 'files_matching', 'ignore_files' + 'dir', 'depth', 'files_matching', 'ignore_files', 'extensions', ] self.VALID_FILE_ARGUMENTS = ['file', '_raw_params'] self.GLOBAL_FILE_ARGUMENTS = ['name'] @@ -96,13 +97,19 @@ class ActionModule(ActionBase): self.depth = self._task.args.get('depth', None) self.files_matching = self._task.args.get('files_matching', None) self.ignore_files = self._task.args.get('ignore_files', None) + self.valid_extensions = self._task.args.get('extensions', self.VALID_FILE_EXTENSIONS) + if isinstance(self.valid_extensions, string_types): + self.valid_extensions = list(self.valid_extensions) + + # validate + if not isinstance(self.valid_extensions, list): + raise AnsibleError('Invalid type for "extensions" option, it must be a list') self._mutually_exclusive() def run(self, tmp=None, task_vars=None): """ Load yml files recursively from a directory. """ - self.VALID_FILE_EXTENSIONS = ['yaml', 'yml', 'json'] if not task_vars: task_vars = dict() @@ -221,7 +228,7 @@ class ActionModule(ActionBase): success = False file_ext = source_file.split('.') if len(file_ext) >= 1: - if file_ext[-1] in self.VALID_FILE_EXTENSIONS: + if file_ext[-1] in self.valid_extensions: success = True return success return success @@ -241,7 +248,7 @@ class ActionModule(ActionBase): failed = True err_msg = ( '{0} does not have a valid extension: {1}' - .format(filename, ', '.join(self.VALID_FILE_EXTENSIONS)) + .format(filename, ', '.join(self.valid_extensions)) ) return failed, err_msg, results