Is it possible to define playbook-global variables in Ansible?

Ansible

Ansible Problem Overview


I have a large Ansible playbook where Docker images are built when running it. I am using an increasing number as the tag to version them. Currently, I have to specify this in every hosts: section.

I know there are global variables but from what I found by searching for "ansible" "global variables", they have to defined outside of the playbook. Is it possible to define global variables which are global for the playbook?

Ansible Solutions


Solution 1 - Ansible

Ansible has a default all group that, funnily enough, contains all the hosts in the inventory file.

As such you can do like with any host groups and provide group_vars for the host group.

As shown in the previous link these can be defined directly in the inventory file or they can be contained in a separate file named after the group in a group_vars directory at the same directory level as the inventory file.

An example directory structure might then look something like:

-ansible
 |--inventory
 |  |--group_vars
 |  |  |--all
 |  |  |--dev
 |  |  |--test
 |  |  |--prod
 |  |  |--webservers
 |  |  |--databases
 |  |--dev
 |  |--test
 |  |--prod
 |--roles
  ...

Your dev inventory file might then look something like:

[dev:children]
webservers
databases

[webservers]
web1.dev
web2.dev

[databases]
database-master.dev
database-slave.dev

All of these hosts will now pick up any host specific config (that could be defined either in line or, just like with group_vars can be put into a host_vars folder) and also config for the specific groups they are in such as webservers and then the groups they also inherit from such as dev but also, by default, all.

This can then be used to configure things in a coarser way than per host.

Things such as NTP servers may want to be defined in all, while DNS servers may want to be defined at the environment level (if your network is segmented into dev, test and production they may need different DNS servers setting in /etc/resolv.conf) while different types of servers may have different configurations around things such as lists of packages to be installed. Finally, some things may need to be host specific such as setting the MySQL server id in a replication group.

If, instead, you only want to define playbook global settings rather than across the inventory (and so could be accessed by other playbooks) then you simply need a vars block in your play definition like so:

- hosts: webservers
  vars:
    http_port: 80
  tasks:
    - name: Task1 to be ran against all the webservers
      ...

As mentioned before, you can always use the all group here too:

- hosts: all
  vars:
    ntp_pool:
      - ntp1.domain
      - ntp2.domain
  tasks:
    - name: Task1 to be ran against all the servers
      ...

In general though, I would strongly recommend using roles to structure what things are ran against certain hosts and then using the inventory to explain what servers are what type and then use a group_vars dir at the inventory level to contain all the variables for those groups of hosts. Doing things this way will help you keep things in sensible places and allow you to easily reuse your code base.

Solution 2 - Ansible

If the tag/version you are using is applicable to all hosts, then using group_vars/all is a viable option.

If the revision numbers are specific to each host entries in a host_vars/host_name file might be better.

If you want to read and initial var and then increment it after each play that becomes a bit more difficult to persist that information across plays (or each -hosts as you say) in the playbook. For example if you were looking to deploy N docker instances you might do some dynamic inventory magic like this:

- hosts: localhost
  tasks:
  - add_host: name=docker_{{item}} groups="dockers,other" tag={{item}}
    with_sequence: start={{ext_def_start}} count={{ext_def_num}}


- hosts: docker_*
  tasks:
  - debug: var=tag

Solution 3 - Ansible

Yes, global vars are possible like this,

sample splunk setup playbook

splunk/
   setup_splunk_playbook.yaml
   roles/base
           /tasks/main.yaml
           /tasks/install.yaml
         search_head
           /tasks/configure.yaml
         indexer
           /tasks/configure.yaml
         some_other_role
           /tasks/some_task.yaml
   hosts
   config.yaml

Place your vars into config.yaml

cat splunk/config.yaml

--- 
# global Splunk variables
splunk_version: 7.0.0

in your playbook, include the Roles

cat setup_splunk_playbook.yaml

- hosts: "search_heads"  
  become_user: root
  become: true
  gather_facts: true
  
  roles:
    - base
    - search_head

in your Role, include the Global Vars inside a Task

cat roles/base/tasks/main.yaml

---
# install Splunk Base

- name: include vars
  include_vars: "{{ playbook_dir }}/config.yaml"

- include: install.yaml

vars are accessible in tasks now,

cat roles/base/tasks/install.yaml

- name: echo version
  debug: splunk version is {{ splunk_version }}

Solution 4 - Ansible

I know this might not answer OP's query exactly, but for people googling to set global variables(lists/arrays) so that they don't have to set them in each task this might be pretty handy.

Its surprisingly simple, Say you have a list of domains that you need to pass, I named the variable goofy just to signify that it could be anything.

- hosts: [yourhostlistgoeshere]
  remote_user: root
  vars:
    domainslisto:
       - site1.com
       - website2.xyz

....



  tasks:
    - name: copy vhosts
      template: src=virtualhost.conf dest=/etc/apache2/sites-available/{{ item }}.conf
      with_items: "{{ domainslisto }}"

    - name: a2ensite {{ item }}
      command: a2ensite {{ item }}
      with_items: "{{ domainslisto }}"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrabejensView Question on Stackoverflow
Solution 1 - AnsibleydaetskcoRView Answer on Stackoverflow
Solution 2 - AnsiblePetro026View Answer on Stackoverflow
Solution 3 - Ansibleperfecto25View Answer on Stackoverflow
Solution 4 - AnsibleMohd Abdul MujibView Answer on Stackoverflow