debops / debops-tools

Your Debian-based data center in a box
https://debops.org/
GNU General Public License v3.0
1.07k stars 116 forks source link

Include fails when done from hooks #153

Closed vshalts closed 8 years ago

vshalts commented 8 years ago

Hi,

I want to split functionality used in hooks into several files (hook called from debops.users). For that I would like to use include from hook. But it doesn't work this way. I extracted smallest possible example to reproduce problem: https://www.dropbox.com/s/fjc1m2n6qwtkqbs/debops-test.zip?dl=0

Short description (in case it will be problems with download): Have two playbooks (test_fail, test_success) and hook spitted into two files (post_main, prezto).

First (test_fail) done the way it is used in all DebOps playbooks will not print Success message - fail. Second (test_success) work fine, but I don't understand why and unfortunately it is not how it done in debops, so I can't use it. Can you please give any suggestion about why first case fail and how can I split playbook called from debops hook? Thanks!

test_fail.yml:


---

- hosts: localhost
  tasks:
    - name: DebOps post_tasks hook
      include: "{{ lookup('task_src', 'users/post_main.yml') }}"

test_success.yml:


---

- hosts: localhost
  tasks:
    - name: DebOps post_tasks hook
      include: "{{ p_path }}"
  vars:
    p_path: "{{ lookup('task_src', 'users/post_main.yml')}}"

post_main.yml:


---

- name: Debug
  debug: msg="{{ lookup('task_src', 'users/prezto.yml') }}"

- name: prezto
  include: "{{ lookup('task_src', 'users/prezto.yml') }}"

prezto.yml:


---

- debug: msg="Success"
drybjed commented 8 years ago

My first guess would be that it is dependent on the order of variable/task resolution in Ansible. IIRC, before Ansible touches the tasks in any way, all variables are resolved first, including lookups.

In the test_fail.yml playbook, the lookup is resolved by Ansible too late, it wants to run all tasks at this point. Not sure what's exactly happening there, you could add a register to that task and debug the output.

In the test_success.yml playbook, Ansible first resolves the play variables, so it has a chance to properly perform the lookup. Next, the task already has the correct path from the lookup so Ansible can process it and include other tasks as you expect.

Remember, that in DebOps, all lookups using custom hooks are performed on the role level, not on the playbook level. IIRC this has its own rules regarding variable/task resolution by Ansible, and that's the reason these lookups work in the roles.

vshalts commented 8 years ago

The same issue appear if hook called from debops.users role. It was the first things I tried. This example was my attempt to create simplified version. Here is updated example that based on roles: https://www.dropbox.com/s/n2z14b0a35i1j77/debops-test_1.zip?dl=0

As I understand it is impossible to call another role from hook, right? So, the only way to split code called in hook that I see is to use includes. What happens: lookup itself work fine and include code from hook (post_main), but if hook itself has include task - include will be ignored (no error messages :( ). So, include from inside hook doesn't work (including case when hook was called from role), but all tasks from hook prior to this include task will work as expected.

I will be glad for any solution/example where hook code spitted into several files. I will appreciate If you point me to any example code where such splitted hook demonstrated. Thanks.

drybjed commented 8 years ago

You're correct, the lookup plugins aren't recursive, so includes present in the included task list won't work. Fixing that would probably require copying at least some code from Ansible that handles include parsing and I think this is outside of the scope of these plugins.

You cannot include other roles using lookup plugins as well, this is meant only for task lists. The task_src lookup plugin was meant to be used to "inject" 2-3 tasks from a file somewhere, in a case where you don't want to write a custom role that replaces the one you are trying to "augment". From your case it seems that you want to extend debops.users beyond what task_src does, so I would just write a replacement debops.users role and put it in the DebOps project directory, in ansible/roles/. That way it should "mask" the default debops.users and let you easily do what you want.

vshalts commented 8 years ago

I see. I am not realized that it is possible to "mask" default roles. That solution will work for me too. Probably will need to merge changes from time to time, but it is ok. Thanks!!

drybjed commented 8 years ago

@vshalts Great. One of the core ideas of DebOps is that roles and playbooks are "read-only" to allow updates using git, therefore there should always be a way to allow user customization. Using roles_path variable to "mask" roles with your own custom ones is one such method of doing that. It's not always perfect, especially when you access things outside of the role itself, so I try not to do that and use different methods to pass data between roles.

vshalts commented 8 years ago

I'll try my best :) Thanks for suggestion!!