0

I've created two very simple Ansible roles called base and web. web is dependent on base and this dependency is defined in web/meta/main.yml.

base has the following task defined in base/tasks/main.yml:

- name: install required packages
  apt:
    name: "{{ install_packages }}"
    update_cache: "{{ apt_update_cache }}"
    cache_valid_time: "{{ apt_cache_valid_time }}"

The variables in base are defined in base/defaults/main.yml:

apt_update_cache: yes
apt_cache_valid_time: 3600

install_packages:
  - ufw
  - sshguard

The variables in web are defined in web/defaults/main.yml:

install_packages:
 - nginx

What I want to do is:

  1. Call install required packages from base, using the install_packages variable from base, and apt_update_cache and apt_cache_valid_time from base.
  2. Call install required packages from web, using the install_packages variable from web, and apt_update_cache and apt_cache_valid_time from base (since I haven't overridden either of those two in web).

Is this possible, and if so how would I go about doing it? Alternatively, is there a 'better' way to achieve the same result, without reproducing the task in every dependent role (I'm likely to create several others which depend on base, and they will all have their own role-specific tasks too)?

pwaring
  • 3,032
  • 8
  • 30
  • 46

1 Answers1

2

Here's one option.

For clarity, rename install_packages in roles/base/defaults/main.yml to base_packages:

---
base_packages:
  - ufw 
  - sshguard

Rewrite your package installation task in roles/base/main.yml so that it looks like this:

---
- name: install required packages
  apt:
    name: "{{ base_packages + extra_packages|default([]) }}"
    update_cache: "{{ apt_update_cache }}"
    cache_valid_time: "{{ apt_cache_valid_time }}"

In roles/web/defaults/main.yml, define web_packages:

---
web_packages:
  - nginx

And in roles/web/meta/main.yml, declare your dependency like this:

---
dependencies:
  - role: base
    vars:
      extra_packages: "{{ web_packages }}"

If I replace that apt task with a debug task:

- name: install required packages
  debug:
    msg:
      apt:
        name: "{{ base_packages + extra_packages|default([]) }}"
        update_cache: "{{ apt_update_cache }}"
        cache_valid_time: "{{ apt_cache_valid_time }}"

And use this playbook:

---
- hosts: localhost
  gather_facts: false
  roles:
    - web

I get the following output:

PLAY [localhost] ******************************************************************************

TASK [base : install required packages] *******************************************************
ok: [localhost] => {
    "msg": {
        "apt": {
            "cache_valid_time": 3600, 
            "name": [
                "ufw", 
                "sshguard", 
                "nginx"
            ], 
            "update_cache": true
        }
    }
}

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

As you can see, this installs both the packages declared in your base role as well as the packages from the web role.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • Thanks for the answer. Will this work if I have multiple roles dependent on `base` though? What happens if I end up creating a role which is dependent on `web`? I'm trying to avoid having parent roles being aware of child roles. – pwaring Apr 14 '19 at 08:46