Ansible Continued

 

Variables

Ansible playbooks can contain variables, whose values affect the running of tasks. Creating variables has the same benefits as making constants does in programming. If we want to change a value that is used in several parts in a playbook, we only need to change the place where the variable is defined.

For example we can place variables at the top of a script for a user name and port number a service could be run under:


- name: Setup some service
  hosts: all
  vars:
    app_port: 8080
    app_user: deployer

  tasks:
    # ...

We can then customize the playbook by modifying them, as needed. To reference those variables we would use double-curly braces, as in:


  - name: Allow new incoming SYN packets on TCP port 22 (SSH)
  ansible.builtin.iptables:
    protocol: tcp
    destination_port: {{ app_port }}
    syn: match
    jump: ACCEPT
    comment: Open the application port

We can also specify or override variable values on the command line when launching a playbook: $ ansible-playbook playbook.yml -e "app_port=9090"


 

Lists

Ansible also supports list variables, which can be given as follows:


vars:
  needed_packages:
    - git
    - vim
    - build-essential

Lists can be combined with the Ansible loop structure. For example, we can install all of the packages in this list with the following:


  tasks:
    - name: Make sure all packages are present
      package:
        name: "{{ item }}"
        state: present
      loop: "{{ needed_packages }}"

The loop structure repeats the task with each element filled in for "item".

We could also reference list items using the familiar brackets syntax. For example, we could refer to the first of these packages in the list with "{{ needed_packages[0] }}".


 

Dictionaries

Ansible also supports dictionary variables which create key/value pairs. For example, we can make a dictionary to associate values to be filled in for a database system:


vars:
  dbinfo:
    name: wp_database
    user: wpuser
    password: bananapie

These can be referenced with either bracket or dot notation, as it "{{ dbinfo[name] }}" or "{{ dbinfo.name }}".

We could also use this to, for example, list the different package names on different systems and install the correct one:


- name: Install Apache regardless of distro
  hosts: localhost
  connection: local
  become: true
  vars:
    apache_pkg:
      Debian: apache2
      RedHat: httpd

  tasks:
    - name: Make sure apache is installed
      package:
        name: "{{ apache_pkg[ansible_os_family] }}"
        state: present

 

Facts

The above example uses the ansible_os_family fact. Ansible gathers facts of the systems that it configures before running playbooks on them. These can be referenced in tasks, often as dictionary keys as in the above example. Other helpful ones are:

FactMeaning
ansible_hostnameShort hostname
ansible_fqdnFully qualified domain name
ansible_os_familyOverall umbrella of operating system, such as "RedHat", "Debian", "Windows", etc.
ansible_distributionMore specific distro name such as "Ubuntu", "CentOS", etc.
ansible_distribution_versionThe version of the distro being used
ansible_architectureThe processor architecture being used, such as "x86_64"
ansible_default_ipv4.addressThe primary IP address
ansible_user_idThe name of the user running the playbook