Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

ansible

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?

like image 348
rabejens Avatar asked Oct 14 '15 13:10

rabejens


People also ask

How are global variables defined in Ansible?

Variable Scopes Ansible has 3 main scopes: Global: this is set by config, environment variables and the command line. Play: each play and contained structures, vars entries, include_vars, role defaults and vars. Host: variables directly associated to a host, like inventory, facts or registered task outputs.

How do you define a variable in playbook?

To define a variable in a playbook, simply use the keyword vars before writing your variables with indentation. To access the value of the variable, place it between the double curly braces enclosed with quotation marks. In the above playbook, the greeting variable is substituted by the value Hello world!

Where can variables be defined for use in Ansible?

You can define these variables in your playbooks, in your inventory, in re-usable files or roles, or at the command line. You can also create variables during a playbook run by registering the return value or values of a task as a new variable.

How do you pass variables in Ansible playbook?

To pass a value to nodes, use the --extra-vars or -e option while running the Ansible playbook, as seen below. This ensures you avoid accidental running of the playbook against hardcoded hosts.


2 Answers

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.

like image 82
ydaetskcoR Avatar answered Sep 21 '22 18:09

ydaetskcoR


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 
like image 38
Petro026 Avatar answered Sep 23 '22 18:09

Petro026