5

Does ansible pass Role Default variables to the Handlers within the same Role?

Here's a minimal excerpt of the playbook that has the issue:

Role hierarchy

- playbook.yml - roles/ - gunicorn/ - defaults/ - main.yml - handlers/ - main.yml - code-checkout/ - tasks/ - main.yml 

Here's the file contents

gunicorn/defaults/main.yml

--- gu_log: "/tmp/gunicorn.log" 

gunicorn/handlers/main.yml

--- - name: Clear Gunicorn Log shell: rm {{ gu_log }} 

finalize/tasks/main.yml

--- - name: Test Handlers shell: ls notify: - Restart Gunicorn 

playbook.yml

--- - name: Deploy hosts: webservers tasks: - include: roles/finalize/tasks/main.yml handlers: - include: roles/gunicorn/handlers/main.yml 

AFAIK everything looks good. However, I get this error during the playbook execution

FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'gu_log' is undefined\n\nThe error appears to have been in '/roles/gunicorn/handlers/main.yml': line 3, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Restart Gunicorn\n ^ here\n"}

Using Ansible 2.2 on Ubuntu 12.04 LTS

Here's a modified version of techraf's script that creates all the directories and demonstrates my issue

#!/bin/bash mkdir -p ./rtindru-test/roles/gunicorn mkdir -p ./rtindru-test/roles/gunicorn/defaults mkdir -p ./rtindru-test/roles/gunicorn/handlers mkdir -p ./rtindru-test/roles/finalize/tasks cat >./rtindru-test/roles/finalize/tasks/main.yml <<HANDLERS_END --- - name: Test Handlers shell: rm {{ gu_log }} HANDLERS_END cat >./rtindru-test/roles/gunicorn/handlers/main.yml <<HANDLERS_END --- - name: Clear Gunicorn Log shell: rm {{ gu_log }} HANDLERS_END cat >./rtindru-test/roles/gunicorn/defaults/main.yml <<DEFAULTS_END --- gu_log: "/tmp/gunicorn.log" DEFAULTS_END cat >./rtindru-test/playbook.yml <<PLAYBOOK_END --- - name: Deploy hosts: localhost tasks: - include: roles/finalize/tasks/main.yml handlers: - include: roles/gunicorn/handlers/main.yml PLAYBOOK_END touch /tmp/gunicorn.log ls -l /tmp/gunicorn.log ansible-playbook ./rtindru-test/playbook.yml ls -l /tmp/gunicorn.log 

Output

PLAY [Deploy]


TASK [setup] ******************************************************************* ok: [localhost]

TASK [Test Handlers] *********************************************************** fatal: [localhost]: FAILED! => {"failed": true, "msg": "the field 'args' has an invalid value, which appears to include a variable that is undefined. The error was: 'gu_log' is undefined\n\nThe error appears to have been in '/rtindru-test/roles/finalize/tasks/main.yml': line 2, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n---\n- name: Test Handlers\n ^ here\n"} to retry, use: --limit @/rtindru-test/playbook.retry

PLAY RECAP ********************************************************************* localhost : ok=1 changed=0 unreachable=0
failed=1

11
  • @techraf Ansible roles are intended to be fairly independent - and this is my "Complete" role. What more information would you need to respond? Commented Dec 22, 2016 at 16:31
  • try gu_log = "/tmp/gunicorn.log" just a guess Commented Dec 22, 2016 at 17:11
  • your inventory and/or playbook is missing Commented Dec 22, 2016 at 17:24
  • Now that you included the missing parts, it is clear you are neither defining nor using any role. You are just including a few files from subdirectories which you named to mimic the directory names inside a role. The answer as I posted before is even more valid - notice roles: inside the playbook. Commented Dec 23, 2016 at 7:25
  • 1
    I already replied in the answer - if you want to use roles, you need to use roles. You can't include one file and expect that the functionality of roles magically appears. I don't understand what you want to achieve by copying the code from the answer to the question, modifying the code to break it, and claiming it does not work. Yes, if you break the code, it does not work. Commented Dec 23, 2016 at 7:36

1 Answer 1

3

You are neither defining nor using any roles. With the following task:

- include: roles/finalize/tasks/main.yml 

you are only including a tasks file into your playbook. It has nothing to do with roles.

To assign a role you should specify a list of roles for a play (one or more):

role: - my_role1 - my_role2 

Please have a look at the documentation on roles and feel free to use the playbook and structure as created by the below script.

Does ansible pass Role Default variables to the Handlers within the same Role?

Yes it does.

For a proof run the following bash script which creates and runs a minimal example. It takes the contents of gunicorn/defaults/main.yml and gunicorn/handlers/main.yml from the question intact and adds missing components: the tasks and the playbook. It creates a file to be removed and runs the playbook.

#!/bin/bash mkdir -p ./so41285033/roles/gunicorn mkdir -p ./so41285033/roles/gunicorn/defaults mkdir -p ./so41285033/roles/gunicorn/handlers mkdir -p ./so41285033/roles/gunicorn/tasks cat >./so41285033/roles/gunicorn/tasks/main.yml <<TASKS_END --- - debug: changed_when: true notify: Clear Gunicorn Log TASKS_END cat >./so41285033/roles/gunicorn/handlers/main.yml <<HANDLERS_END --- - name: Clear Gunicorn Log shell: rm {{ gu_log }} when: "'apiservers' not in group_names" HANDLERS_END cat >./so41285033/roles/gunicorn/defaults/main.yml <<DEFAULTS_END --- gu_log: "/tmp/gunicorn.log" DEFAULTS_END cat >./so41285033/playbook.yml <<PLAYBOOK_END --- - hosts: localhost gather_facts: no connection: local roles: - gunicorn PLAYBOOK_END touch /tmp/gunicorn.log ls -l /tmp/gunicorn.log ansible-playbook ./so41285033/playbook.yml ls -l /tmp/gunicorn.log 

The result:

-rw-r--r-- 1 techraf wheel 0 Dec 23 07:57 /tmp/gunicorn.log [WARNING]: Host file not found: /etc/ansible/hosts [WARNING]: provided hosts list is empty, only localhost is available PLAY [localhost] *************************************************************** TASK [gunicorn : debug] ******************************************************** ok: [localhost] => { "msg": "Hello world!" } RUNNING HANDLER [gunicorn : Clear Gunicorn Log] ******************************** changed: [localhost] [WARNING]: Consider using file module with state=absent rather than running rm PLAY RECAP ********************************************************************* localhost : ok=2 changed=2 unreachable=0 failed=0 ls: /tmp/gunicorn.log: No such file or directory 

Interpretation:

  • Before running the playbook the file /tmp/gunicorn.log was created and its existence verified:

    -rw-r--r-- 1 techraf wheel 0 Dec 23 07:57 /tmp/gunicorn.log 
  • After running the playbook the file /tmp/gunicorn.log does not exist:

    ls: /tmp/gunicorn.log: No such file or directory 
  • Ansible correctly passed the variable gu_log value to the Clear Gunicorn Log handler which removed the file.

Final remark:

The problem described in question is impossible to reproduce, because the question does not contain complete nor verifiable example in the meaning of MCVE.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a bunch! I understand your point about the question being incomplete - I've added details based on your comments. One point of difference I notice immediately is that my playbook includes individual tasks instead of roles. Another difference is that gunicorn (which has no "tasks/main.yml") is included ONLY in the handlers section (not in tasks or roles).
Two quick followup questions: 1. Is it recommended to include roles the way you have? What if one of my roles is purely a handler as is the case with the gunicorn role 2. Is it necessary to include a role/task explicitly for the variables to be available to the it's handler?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.