Lazy evaluation of "composed" default variable in dependent Ansible role
I have two Ansible roles, let's call them postgres
and myservice
.
In my postgres
role, I define a few default variables (in postgres/defaults/main.yml
):
postgres_db: pgdb
postgres_user: postgres
postgres_systemd_docker_service_name: postgres_{{postgres_db}}
In my postgres
role, I create a systemd service unit file from the postgres_systemd_docker_service_name
variable. The idea here being that if I want to run more than one postgres docker containers for multiple services, I can distinguish them using the postgres_db
variable.
Then I have the myservice
role, in which I depend on the postgres
role and override some of the default variables.
In my myservice/meta/main.yml
:
dependencies:
- {role: docker}
- role: postgres
postgres_user: "myservice_user"
postgres_password: "myservice_password"
postgres_db: "myservice"
However, when I run a playbook that uses the myservice
role, it will create my systemd unit files as postgres_pgdb
(which is the default value) rather than as postgres_myservice
.
If I use the postgres_systemd_docker_service_name
variable in my myservice
role, it gets evaluated as postgres_myservice
.
Is there any way for me to ensure that the composite variable in my postgres
role is evaluated in such a way that my myservice
role can override the default values?
Solution 1:
Trying a small example, I found that (using Ansible 2.4) a composed default variable (i.e on that is in the defaults/main.yml
) will only be interpolated when that default value is used for the first time.
Example, using only a single role:
roles/certs/defaults/main.yml
---
certs_dir: /etc/pki/tls/certs
cert_files:
- "{{ ssl_domain }}.crt"
- "{{ ssl_domain }}.key"
- "{{ ssl_domain }}_ca-bundle.crt"
roles/certs/tasks/main.yml
---
- name: Determine the subdomain for the current host
command: hostname --domain
register: domain_result
- name: Set domain name as fact
set_fact:
ssl_domain: "{{ domain_result.stdout.strip() }}"
- name: Download certificates
get_url:
url: "http://{{ intranet_certificate_host }}/{{ intranet_certificate_path }}/_.{{ ssl_domain }}/{{ item }}"
dest: "{{ certs_dir }}"
with_items: "{{ cert_files }}"
This will work. I see this is not involving a "dependent" role, but as facts work like that across roles, I am nigh certain this will work across roles just as well.
So, at least in the version that I used, lazy evaluation is the default behaviour, you only need to combine it with set_fact
to provide the value that goes inside the composed default.