How can I persist an ansible variable across ansible roles?

NB: This was written referring to Ansible 1.X. I suspect variable parsing and scoping has changed considerably with Ansible 2.0, so bear that in mind. I'll try to update the answer if I get time (or maybe someone else will answer for v2.0!)

There are two options here. The simplest is to define the variables in your top-level playbook, then propagate them down into your various roles. You can either set these as simple vars, or use pre_tasks to lookup / calculate values dynamically, e.g.

vars:
    foo_static: "value_bar"

pre_tasks:
    - set_fact:
        foo_ncpu: "{{ ansible_processor_vcpus }}"

  roles:
    - {role: role1, role1_var1: "{{foo_static}}", role1_var2: "{{foo_ncpu}}" }
    - {role: role2, role2_var1: "{{foo_static}}", role2_var2: "{{foo_ncpu}}" }

The second option requires that you add a task to whichever role you need to extract a variable from (though since all ansible roles are open-source, that should be easy enough). The trick is to use set_fact to export a variable as a 'host_fact', e.g.

- name: Export role1_varfoo to a 'host-fact' type variable
  set_fact:
    role1_varfoo: "{{ role1_varfoo }}"

Which can then be accessed later like so:

  vars:
    role2_varfoo: "{{ hostvars['myhost']['role1_varfoo']}}"

As described in this bit of the ansible docs.

Note that if you always want to lookup the hostvars of the current machine you're running commands on (without knowing what it's actually called in the ansible hosts file), you can use the variable inventory_hostname like so:

  vars:
    role2_varfoo: "{{ hostvars[inventory_hostname]['role1_varfoo']}}"

(Note lack of quote-marks, since it's a variable, not a string-literal.)

Slightly awkward, but those combinations have met all my needs so far.


Try moving your variable declarations into a pre_task block. Variables set here should be available within and following roles.

https://docs.ansible.com/playbooks_roles.html#roles

e.g.

pre_tasks:
    - name: build load balancer
      os_load_balancer: net=mc_net ext_net=vlan3320 name=load_balancer protocol=HTTPS port=80
      register: my_lb

roles:
  - { role: some_role }

Update: To access the variable using the hostvars syntax use the appropriate host GROUP variable rather than the host that executed the set_fact:

hostvars[inventory_hostname]['variable']

To broaden the accepted question.

1.-You can define ANOTHER role where you register the variable and then set it there then refer that variable from multiple roles. AS LONG as the roles are in the same play. Docu here: http://docs.ansible.com/ansible/playbooks_variables.html#variable-examples

Generally speaking, variables set in one role are available to others. This means if you have a roles/common/vars/main.yml you can set variables in there and make use of them in other roles and elsewhere in your playbook

Edit: Clarification, this applies for REGISTERED and set variables in Ansible 2.x in my experience.

2.-As far as using hostvars goes, I tried it myself and failed with this error:

fatal: [localhost]: FAILED! => {"failed": true, "msg": "'dict object' has no attribute 'ec2_instance_id'"} 

I my case I was doing the following.

- hosts: localhost
  gather_facts: yes
  roles:
  - { role: role_1 }
post_tasks:
- name: Check instance variables within localhost
  debug: var={{ hostvars['localhost']['ec2_instance_id'] }}

On role 1 I had:

- name: register instance_id
  set_fact: ec2_instance_id="{{ item.id }}"
  with_items: "{{ ec2_instance.instances }}"

Although according to this old thread, the hostvar approach should work:

https://github.com/ansible/ansible/issues/1934

Tags:

Ansible