Skip to content

Instantly share code, notes, and snippets.

@mildred
Last active January 15, 2016 07:30
Show Gist options
  • Save mildred/9ce28b926b567548037d to your computer and use it in GitHub Desktop.
Save mildred/9ce28b926b567548037d to your computer and use it in GitHub Desktop.
How Ansible modules are executed

Modules that require transfer between the local machine and the remote

These are hardcoded server-side. See for example the source code for the fetch module. It is empty with a comment stating it is a virtual module.

Other modules

Call stack:

  • Runner._execute_module() in ansible/runner/__init__.py
  • Runner._configure_module() in ansible/runner/__init__.py
  • ModuleReplacer.modify_module() in ansible/module_common.py
  • ModuleReplacer._find_snippets_imports() in ansible/module_common.py

To sum things up:

  • the module is looked up on the ansible library path
  • the file is loaded in memory
  • some strings are looked for, and if found in the module file, will modify how it will be called
    • If WANT_JSON can be found on the file, the type is set to non_native_want_json
    • If a python import from the ansible modules is found (from ansible.module_utils.) or a python replacer is found then the type is set to new
    • else the type is set to old
  • some strings are replaced. Mostly python imports are replaced by the actual python module content and magic replacer strings are replaced with boilerplate code and arguments in python format result of repr().
    • "<<INCLUDE_ANSIBLE_MODULE_ARGS>>" is replaced by the python expression for the arguments
    • "<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>" is replaced by the python expression for the complex arguments
  • the shebang is parsed
  • ModuleReplacer then returns to Runner with the replaced module source code, the detected type of module and the shebang
  • depending on the module type, the Runner will call the module differently.
    • old modules: These are considered executable scripts and will be called with the interpreter in the shebang and an argument file containing arguments in the form var=val var2=val2 that is compatible with shell scripts
    • non_native_want_json modules: Same as old but the argument file will be a JSON file. This can enable more complex arguments
    • new modules: These are generally python scripts and support more features such as the check mode (testing changes but not doing anything to change the target) and no_log (whatever that means). Arguments are passed by string replacement in the source code. These modules are still executed by the interpreter in the shebang, so you could write it in any language and parse arguments replaced in source code.

To test some of this, the following module was used:

#!/bin/bash
: from ansible.module_utils.
: WANT_JSON

#(
cat <<EOF
args:
"<<INCLUDE_ANSIBLE_MODULE_ARGS>>"

complex args:
"<<INCLUDE_ANSIBLE_MODULE_COMPLEX_ARGS>>"

version:
"<<ANSIBLE_VERSION>>"
EOF
env
echo "$@"
echo =====begin=====
cat ${1:-/dev/null}
echo
echo ======end======
#) | logger
exit 1

And the following playbook:

---
- hosts: localhost
  sudo: yes
  tasks:
    - test:
        a: b
        c: ["d", "e"]
      #  yml: file
      #  yes: true
      #  no:
      #    - nein
      #    - non
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment