Answers: <p>Given the <em>foo</em> defaults</p>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; cat roles/foo/defaults/main.yml 
  foo_path: /tmp/test.txt
  </code></pre>
  <p>There are more options:</p>
  <ol>
  <li>Include the <em>foo</em> defaults into a dictionary and get the variable <em>foo_path</em></li>
  </ol>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; cat pb_bar.yml
  - hosts: localhost
    pre_tasks:
      - include_vars:
          file: roles/foo/defaults/main.yml
          name: foo_defaults
      - debug:
          var: foo_defaults.foo_path
        when: debug|d(false)|bool
      - set_fact:
          foo_path: &quot;{{ foo_defaults.foo_path }}&quot;
    roles:
      - bar
  </code></pre>
  <p>Use the variable in the role <em>bar</em></p>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; cat roles/bar/tasks/main.yml
  - stat:
      path: &quot;{{ foo_path }}&quot;
    register: foo_path_st
  - debug:
      var: foo_path_st
    when: debug|d(false)|bool
  - assert:
      that: foo_path_st.stat.exists
  </code></pre>
  <p>gives</p>
  <sup>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; ansible-playbook pb_bar.yml -e debug=true
  
  PLAY [localhost] *****************************************************************************
  
  TASK [include_vars] **************************************************************************
  ok: [localhost]
  
  TASK [debug] *********************************************************************************
  ok: [localhost] =&gt; 
    foo_defaults.foo_path: /tmp/test.txt
  
  TASK [set_fact] ******************************************************************************
  ok: [localhost]
  
  TASK [Assert foo_path] ***********************************************************************
  skipping: [localhost]
  
  TASK [bar : stat] ****************************************************************************
  ok: [localhost]
  
  TASK [bar : debug] ***************************************************************************
  ok: [localhost] =&gt; 
    foo_path_st:
      ansible_facts:
        discovered_interpreter_python: /usr/bin/python3
      changed: false
      failed: false
      stat:
        ...
        exists: true
        ...
        path: /tmp/test.txt
  
  TASK [bar : assert] **************************************************************************
  ok: [localhost] =&gt; changed=false 
    msg: All assertions passed
  
  PLAY RECAP ***********************************************************************************
  localhost: ok=6    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
  </code></pre>
  </sup>
  <hr>
  <ol start="2">
  <li>Structure the roles' tasks</li>
  </ol>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; tree roles
  roles
  ├── bar
  │   └── tasks
  │       └── main.yml
  └── foo
      ├── defaults
      │   └── main.yml
      └── tasks
          ├── assert_foo_path.yml
          ├── install_foo_path.yml
          └── main.yml
  
  5 directories, 5 files
  </code></pre>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; cat roles/foo/tasks/assert_foo_path.yml 
  - stat:
      path: &quot;{{ foo_path }}&quot;
    register: foo_path_st
  - debug:
      var: foo_path_st
    when: debug|d(false)|bool
  - assert:
      that: foo_path_st.stat.exists
  
  shell&gt; cat roles/foo/tasks/install_foo_path.yml 
  - file:
      path: &quot;{{ foo_path }}&quot;
      state: touch
  
  shell&gt; cat roles/foo/tasks/main.yml 
  - name: Install foo_path
    include_tasks: install_foo_path.yml
  - name: Assert foo_path
    include_tasks: assert_foo_path.yml
  </code></pre>
  <p>and use the module <a href="https://docs.ansible.com/ansible/latest/collections/ansible/builtin/include_role_module.html#ansible-builtin-include-role-module-load-and-execute-a-role" rel="nofollow noreferrer"><em>include_role</em></a></p>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; cat roles/bar/tasks/main.yml 
  - name: Assert foo_path
    include_role:
      name: foo
      tasks_from: assert_foo_path.yml
  </code></pre>
  <p>Create playbooks for testing</p>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; cat pb_foo.yml 
  - hosts: localhost
    roles:
      - foo
  
  shell&gt; cat pb_bar.yml 
  - hosts: localhost
    roles:
      - bar
  </code></pre>
  <p>The play will fail if the file is missing</p>
  <sup>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; ansible-playbook pb_bar.yml -e debug=false
  
  PLAY [localhost] *****************************************************************************
  
  TASK [Assert foo_path] ***********************************************************************
  
  TASK [foo : stat] ****************************************************************************
  ok: [localhost]
  
  TASK [foo : debug] ***************************************************************************
  skipping: [localhost]
  
  TASK [foo : assert] **************************************************************************
  fatal: [localhost]: FAILED! =&gt; changed=false 
    assertion: foo_path_st.stat.exists
    evaluated_to: false
    msg: Assertion failed
  
  PLAY RECAP ***********************************************************************************
  localhost: ok=1    changed=0    unreachable=0    failed=1    skipped=1    rescued=0    ignored=0
  </code></pre>
  </sup>
  <p>Create the file</p>
  <sup>
  <pre class="lang-yaml prettyprint-override"><code>shell&gt; ansible-playbook pb_foo.yml -e debug=false
  
  PLAY [localhost] *****************************************************************************
  
  TASK [foo : Install foo_path] ****************************************************************
  included: /export/scratch/tmp7/test-321/roles/foo/tasks/install_foo_path.yml for localhost
  
  TASK [foo : file] ****************************************************************************
  changed: [localhost]
  
  TASK [foo : Assert foo_path] *****************************************************************
  included: /export/scratch/tmp7/test-321/roles/foo/tasks/assert_foo_path.yml for localhost
  
  TASK [foo : stat] ****************************************************************************
  ok: [localhost]
  
  TASK [foo : debug] ***************************************************************************
  skipping: [localhost]
  
  TASK [foo : assert] **************************************************************************
  ok: [localhost] =&gt; changed=false 
    msg: All assertions passed
  
  PLAY RECAP ***********************************************************************************
  localhost: ok=5    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
  </code></pre>
  </sup>
  <p>The assert task will succeed now</p>
  <pre class="lang-yaml prettyprint-override"><code>TASK [foo : assert] **************************************************************************
  ok: [localhost] =&gt; changed=false 
    msg: All assertions passed
  </code></pre>
  
Answers: CC BY-SA 4.0
Answers: 2023-05-04T14:59:29.407Z
Answers: The splitting of the tasks is interesting, I hadn't thought of that.  I don't necessarily like #1 because the `foo` role will always need that variable to be defined and that is not apparent when creating the play.  It'd also be cumbersome and redundant to have to do that for every playbook that decides to include that role.
Answers: FuriousGeorge
Answers: CC BY-SA 4.0
Answers: 2023-05-04T03:57:57.247Z
Answers: 2023-05-04T04:25:26.273Z
Answers: 2023-05-04T04:25:26.273Z
Answers: Vladimir Botka
Body: <p>I have a role, <code>foo</code> that installs a file <code>{{ foo_path }}</code> that's defined in <code>roles/defaults/main.yml</code>.</p>
  <p>I have a second role, <code>bar</code> that depends on that file being there.   I could put <code>foo</code> in the <code>roles/meta/main.yml</code> <code>dependencies</code> but then it will run the entire role which is not ideal. I could potentially tag the task in the role that creates the file, but that's not really scalable, and introduces problems when I'm not the owner of that role's code.</p>
  <p>I could just <code>assert</code> that the file is there, but the problem is that I don't know where &quot;there&quot; is.</p>
  <p>How can I load the <code>foo_path</code> var from a different role without the overhead of running the play?</p>
  
Tags: <ansible>
Title: Ansible role depend on other roles
UserDisplayName: FuriousGeorge
ThreadText: # Ansible role depend on other roles
  
  (Asked by: username_0 on 2023-05-03)
  
  I have a role, `foo` that installs a file `{{ foo_path }}` that's defined in `roles/defaults/main.yml`.
  
  I have a second role, `bar` that depends on that file being there. I could put `foo` in the `roles/meta/main.yml` `dependencies` but then it will run the entire role which is not ideal. I could potentially tag the task in the role that creates the file, but that's not really scalable, and introduces problems when I'm not the owner of that role's code.
  
  I could just `assert` that the file is there, but the problem is that I don't know where "there" is.
  
  How can I load the `foo_path` var from a different role without the overhead of running the play?
  
  **Tags:** ansible
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2023-05-04. Score: 2
  
  Given the *foo* defaults
  
  ```yaml
  shell> cat roles/foo/defaults/main.yml 
  foo_path: /tmp/test.txt
  
  ```
  
  There are more options:
  
  1. Include the *foo* defaults into a dictionary and get the variable *foo\_path*
  
  ```yaml
  shell> cat pb_bar.yml
  - hosts: localhost
    pre_tasks:
      - include_vars:
          file: roles/foo/defaults/main.yml
          name: foo_defaults
      - debug:
          var: foo_defaults.foo_path
        when: debug|d(false)|bool
      - set_fact:
          foo_path: "{{ foo_defaults.foo_path }}"
    roles:
      - bar
  
  ```
  
  Use the variable in the role *bar*
  
  ```yaml
  shell> cat roles/bar/tasks/main.yml
  - stat:
      path: "{{ foo_path }}"
    register: foo_path_st
  - debug:
      var: foo_path_st
    when: debug|d(false)|bool
  - assert:
      that: foo_path_st.stat.exists
  
  ```
  
  gives
  
  ```yaml
  shell> ansible-playbook pb_bar.yml -e debug=true
  
  PLAY [localhost] *****************************************************************************
  
  TASK [include_vars] **************************************************************************
  ok: [localhost]
  
  TASK [debug] *********************************************************************************
  ok: [localhost] => 
    foo_defaults.foo_path: /tmp/test.txt
  
  TASK [set_fact] ******************************************************************************
  ok: [localhost]
  
  TASK [Assert foo_path] ***********************************************************************
  skipping: [localhost]
  
  TASK [bar : stat] ****************************************************************************
  ok: [localhost]
  
  TASK [bar : debug] ***************************************************************************
  ok: [localhost] => 
    foo_path_st:
      ansible_facts:
        discovered_interpreter_python: /usr/bin/python3
      changed: false
      failed: false
      stat:
        ...
        exists: true
        ...
        path: /tmp/test.txt
  
  TASK [bar : assert] **************************************************************************
  ok: [localhost] => changed=false 
    msg: All assertions passed
  
  PLAY RECAP ***********************************************************************************
  localhost: ok=6    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
  
  ```
  
  ---
  
  2. Structure the roles' tasks
  
  ```yaml
  shell> tree roles
  roles
  ├── bar
  │   └── tasks
  │       └── main.yml
  └── foo
      ├── defaults
      │   └── main.yml
      └── tasks
          ├── assert_foo_path.yml
          ├── install_foo_path.yml
          └── main.yml
  
  5 directories, 5 files
  
  ```
  
  ```yaml
  shell> cat roles/foo/tasks/assert_foo_path.yml 
  - stat:
      path: "{{ foo_path }}"
    register: foo_path_st
  - debug:
      var: foo_path_st
    when: debug|d(false)|bool
  - assert:
      that: foo_path_st.stat.exists
  
  shell> cat roles/foo/tasks/install_foo_path.yml 
  - file:
      path: "{{ foo_path }}"
      state: touch
  
  shell> cat roles/foo/tasks/main.yml 
  - name: Install foo_path
    include_tasks: install_foo_path.yml
  - name: Assert foo_path
    include_tasks: assert_foo_path.yml
  
  ```
  
  and use the module [*include\_role*](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/include_role_module.html#ansible-builtin-include-role-module-load-and-execute-a-role)
  
  ```yaml
  shell> cat roles/bar/tasks/main.yml 
  - name: Assert foo_path
    include_role:
      name: foo
      tasks_from: assert_foo_path.yml
  
  ```
  
  Create playbooks for testing
  
  ```yaml
  shell> cat pb_foo.yml 
  - hosts: localhost
    roles:
      - foo
  
  shell> cat pb_bar.yml 
  - hosts: localhost
    roles:
      - bar
  
  ```
  
  The play will fail if the file is missing
  
  ```yaml
  shell> ansible-playbook pb_bar.yml -e debug=false
  
  PLAY [localhost] *****************************************************************************
  
  TASK [Assert foo_path] ***********************************************************************
  
  TASK [foo : stat] ****************************************************************************
  ok: [localhost]
  
  TASK [foo : debug] ***************************************************************************
  skipping: [localhost]
  
  TASK [foo : assert] **************************************************************************
  fatal: [localhost]: FAILED! => changed=false 
    assertion: foo_path_st.stat.exists
    evaluated_to: false
    msg: Assertion failed
  
  PLAY RECAP ***********************************************************************************
  localhost: ok=1    changed=0    unreachable=0    failed=1    skipped=1    rescued=0    ignored=0
  
  ```
  
  Create the file
  
  ```yaml
  shell> ansible-playbook pb_foo.yml -e debug=false
  
  PLAY [localhost] *****************************************************************************
  
  TASK [foo : Install foo_path] ****************************************************************
  included: /export/scratch/tmp7/test-321/roles/foo/tasks/install_foo_path.yml for localhost
  
  TASK [foo : file] ****************************************************************************
  changed: [localhost]
  
  TASK [foo : Assert foo_path] *****************************************************************
  included: /export/scratch/tmp7/test-321/roles/foo/tasks/assert_foo_path.yml for localhost
  
  TASK [foo : stat] ****************************************************************************
  ok: [localhost]
  
  TASK [foo : debug] ***************************************************************************
  skipping: [localhost]
  
  TASK [foo : assert] **************************************************************************
  ok: [localhost] => changed=false 
    msg: All assertions passed
  
  PLAY RECAP ***********************************************************************************
  localhost: ok=5    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
  
  ```
  
  The assert task will succeed now
  
  ```yaml
  TASK [foo : assert] **************************************************************************
  ok: [localhost] => changed=false 
    msg: All assertions passed
  
  ```
  
  > **Comments:**
  > **username_0**: The splitting of the tasks is interesting, I hadn't thought of that.  I don't necessarily like #1 because the `foo` role will always need that variable to be defined and that is not apparent when creating the play.  It'd also be cumbersome and redundant to have to do that for every playbook that decides to include that role.  
  
  ---
  
  