Ansible: Access Host/group Vars From Within Custom Module
Solution 1:
Is there a way how one can access host/group vars from within a custom written module?
Not built-in.
You will have to pass them yourself one way or the other:
- Module args.
- Serialize to local file system (with
pickle
oryaml.dump()
orjson
or ...) and send the file over. - any other innovative ideas you can come up with.
Unfortunately you can't just send over whole host/groupvar files as-it-is because you would have to implement the variable scope/precedence resolution algorithm of ansible which is undefined (it's not the Zen philosophy of ansible to define such petty things :P ).
Solution 2:
I think you pretty much hit the nail on the head with your thinking here:
I guess it is not possible, since the module runs on the target machine and probably the facts/host/group vars are not transferred along with the module...
However, having said that, if you really have a need for this then there might be a slightly messy way of doing it. As of Ansible 1.8 you can set up fact caching, which uses redis to cache facts between runs of plays. Since redis is pretty easy to use and has clients for most popular programming languages, you could have your module query the redis server for any facts you need. It's not exactly the cleanest way to do it, but it just might work.
Solution 3:
As per your suggestion in your answer here, I did manage to read host_vars and local play vars through a custom Action Plugin.
I'm posting this answer for completeness sake and to give an explicit example of how one might go about this method, although you gave this idea originally :)
Note - this example is incomplete in terms of a fully functioning plugin. It just shows the how to access variables.
from ansible.template import is_template
from ansible.plugins.action import ActionBase
classActionModule(ActionBase):
defrun(self, tmp=None, task_vars=None):
# some boilerplate ...# init
result = super(ActionModule, self).run(tmp, task_vars)
# more boilerplate ...# check the arguments passed to the task, where if missing, return None
self._task.args.get('<TASK ARGUMENT NAME>', None)
# or# check if the play has vars defined
task_vars['vars']['<ARGUMENT NAME>']
# or# check if the host vars has something defined
task_vars['hostvars']['<HOST NAME FORM HOSTVARS>']['<ARGUMENT NAME>']
# again boilerplate...# build arguments to pass to the module
some_module_args = dict(
arg1=arg1,
arg2=arg2
)
# call the module with the above arguments...
In case you have your playbook variables with jinja 2 templates, you can resolve these templates in the plugin as follows:
from ansible.template import is_template
# check if the variable is a template through 'is_template'if is_template(var, self._templar.environment):
# access the internal `_templar` object to resolve the template
resolved_arg = self._templar.template(var_arg)
Some words of caution:
- If you have a variable defined in your playbook as follows
# things ...#vars:-pkcs12_path:'{{ pkcs12_full_path }}'-pkcs12_pass:'{{ pkcs12_password }}'
The variable pkcs12_path
must not match the host_vars name.
For instance, if you had pkcs12_path: '{{ pkcs12_path }}'
, then resolving the template with the above code will cause a recursive exception... This might be obvious to some, but for me it was surprising that the host_vars variable and the playbook variable must not be with the same name.
- You can also access variables through
task_vars['<ARG_NAME>']
, but I'm not sure where it's reading this from. Also it's less explicit than taking variables fromtask_vars['vars']['<ARG_NAME>']
or from the hostvars.
- You can also access variables through
PS - in the time of writing this, the example follows the basic structure of what Ansible consider an Action Plugin. In the future, the run
method might change its signature...
Post a Comment for "Ansible: Access Host/group Vars From Within Custom Module"