Last active
November 2, 2015 16:36
-
-
Save dvarrazzo/7418a89b7278ff69267c to your computer and use it in GitHub Desktop.
Ansible Plugin implementing the include_defaults action.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Ansible Plugin implementing the include_defaults action. | |
Like include_vars, but the included defaults can be overridden by the | |
inventory or by group vars. Can be used to read the defaults from another role. | |
Usage: drop it into a directory called ``action_plugins`` in your playbook | |
directory. Then you can use it with:: | |
- name: get the defaults from the web server role | |
action: include_defaults roles/web/defaults/main.yml | |
Proposed for inclusion in <https://github.com/ansible/ansible/pull/8808>. | |
""" | |
# (c) 2014 Daniele Varrazzo <[email protected]> | |
import os | |
from ansible.utils import template | |
from ansible import utils | |
from ansible import errors | |
from ansible.runner.return_data import ReturnData | |
class ActionModule(object): | |
TRANSFERS_FILES = False | |
def __init__(self, runner): | |
self.runner = runner | |
def run(self, conn, tmp, module_name, module_args, inject, complex_args=None, **kwargs): | |
if not module_args: | |
result = dict(failed=True, msg="No source file given") | |
return ReturnData(conn=conn, comm_ok=True, result=result) | |
source = module_args | |
source = template.template(self.runner.basedir, source, inject) | |
if '_original_file' in inject: | |
source = utils.path_dwim_relative(inject['_original_file'], 'defaults', source, self.runner.basedir) | |
else: | |
source = utils.path_dwim(self.runner.basedir, source) | |
if os.path.exists(source): | |
data = utils.parse_yaml_from_file(source, vault_password=self.runner.vault_pass) | |
if data and type(data) != dict: | |
raise errors.AnsibleError("%s must be stored as a dictionary/hash" % source) | |
elif data is None: | |
data = {} | |
inject['defaults'].update(data) | |
return ReturnData(conn=conn, comm_ok=True, result={}) | |
else: | |
result = dict(failed=True, msg="Source file not found.", file=source) | |
return ReturnData(conn=conn, comm_ok=True, result=result) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Warning! unfortunately this implementation of
include_defaults
has an issue: because it changes some data structures in-place it doesn't work when ansible runs in parallel on many hosts, because the process forks and the modified variables get lost.In my case, I have solved the issue by adding a
vars_files
list to thegroup_vars
files: the list usually contains the name of the file invars_files
itself but it can contain further customization (can create configurations "inheriting" from a base one and tweaking a few things). I've then converted every task file where I was usinginclude_defaults
intoinclude_vars
, with a final include ofvars_files
too, in order to have the values specified invars_files
to override the "defaults" (which become too powerful otherwise). E.g. if a web client should know the port of the web server, you can have:roles/web_server/defaults/main.yml
:group_files/testsite
:roles/web_client/tasks/main.yml
: