Skip to content

Variables and Facts

Variable Types

Basic Variables

# Simple variables
string_var: "Hello World"
number_var: 42
boolean_var: true
list_var: 
  - item1
  - item2
  - item3
dict_var:
  key1: value1
  key2: value2
  nested:
    key3: value3

Special Variables

# Ansible predefined variables
ansible_host: "192.168.1.10"
ansible_port: 22
ansible_user: "deploy"
ansible_connection: "ssh"

# Magic variables
inventory_hostname: "web1.example.com"
group_names: ["webservers", "production"]
hostvars: {}
groups: {}

Variable Scope

Host Variables

# host_vars/web1.example.com.yml
apache_port: 80
doc_root: "/var/www/html"

Group Variables

# group_vars/webservers.yml
http_port: 80
max_clients: 200

Play Variables

- name: Configure web servers
  hosts: webservers
  vars:
    http_port: 80
    max_clients: 200
  vars_files:
    - vars/common.yml
    - vars/secure.yml

Role Variables

# roles/webserver/defaults/main.yml
http_port: 80
doc_root: "/var/www/html"

# roles/webserver/vars/main.yml
nginx_version: "stable"

Variable Precedence

  1. Command line (-e or --extra-vars)
  2. Task variables
  3. Block variables
  4. Role and include variables
  5. Play variables
  6. Host facts
  7. Host vars
  8. Group vars
  9. Role defaults
  10. Inventory variables

Facts

System Facts

- name: Display system facts
  debug:
    msg: |
      OS Family: {{ ansible_os_family }}
      Distribution: {{ ansible_distribution }}
      Distribution Version: {{ ansible_distribution_version }}
      Architecture: {{ ansible_architecture }}
      Processor Cores: {{ ansible_processor_cores }}
      Total Memory: {{ ansible_memtotal_mb }}

Custom Facts

# /etc/ansible/facts.d/custom.fact
[application]
version=1.0.0
environment=production
deployed_date=2024-03-15

Using Facts

- name: Use custom facts
  debug:
    msg: "App version: {{ ansible_local.custom.application.version }}"

Variable Manipulation

Filters

# String manipulation
uppercase: "{{ variable | upper }}"
lowercase: "{{ variable | lower }}"
json_string: "{{ variable | to_json }}"
yaml_string: "{{ variable | to_yaml }}"

# List manipulation
first_item: "{{ list_var | first }}"
last_item: "{{ list_var | last }}"
sorted_list: "{{ list_var | sort }}"
unique_items: "{{ list_var | unique }}"

# Dictionary manipulation
dict_keys: "{{ dict_var | dict2items }}"
combined_dict: "{{ dict1 | combine(dict2) }}"

Jinja2 Operations

# Conditionals
result: "{{ 'high' if value > 90 else 'low' }}"

# Loops
devices: "{{ ['sda', 'sdb', 'sdc'] | map('regex_replace', '^', '/dev/') | list }}"

# Math operations
total: "{{ value1 + value2 }}"
percentage: "{{ (value / total * 100) | round(2) }}"

Variables in Templates

Template Usage

# templates/nginx.conf.j2
server {
    listen {{ http_port }};
    server_name {{ server_name }};

    {% for domain in allowed_domains %}
    server_name {{ domain }};
    {% endfor %}

    location / {
        root {{ doc_root }};
        {% if enable_php %}
        index index.php index.html;
        {% else %}
        index index.html;
        {% endif %}
    }
}

Environment Variables

Setting Environment Variables

- name: Run with environment variables
  shell: echo $DATABASE_URL
  environment:
    DATABASE_URL: "postgresql://user:pass@localhost/db"
    API_KEY: "{{ lookup('env', 'API_KEY') }}"

Using Environment Files

- name: Load environment file
  include_vars:
    file: "{{ env }}.yml"
    name: env_vars

Variable Registration

Registering Task Output

- name: Check service status
  command: systemctl status nginx
  register: service_status
  ignore_errors: true

- name: Display service status
  debug:
    msg: "Nginx is {{ 'running' if service_status.rc == 0 else 'stopped' }}"

Lookups

File Lookups

password: "{{ lookup('file', '/path/to/password.txt') }}"
ssh_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"

Other Lookups

# Environment variables
api_key: "{{ lookup('env', 'API_KEY') }}"

# DNS lookup
ip_address: "{{ lookup('dig', 'example.com') }}"

# Random values
random_password: "{{ lookup('password', '/dev/null length=16 chars=ascii_letters,digits') }}"

# AWS Secret
aws_secret: "{{ lookup('aws_secret', 'myapp/db_password') }}"

Variable Protection

Vault Protection

# vars/secure.yml
db_password: !vault |
  $ANSIBLE_VAULT;1.1;AES256
  66386439653236336462626566653063336164663966303231363934653561363964363833313662
  6431626536303530376336343832656537303632313433360a626438346336353331386135323734
  62656361653630373231613662633962316233633936396165386439616533353965373339616234
  3430613539666330390a373661636536358

# Using vault variables
- name: Configure database
  template:
    src: db_config.j2
    dest: /etc/app/database.conf
  vars_files:
    - vars/secure.yml

No Log Option

- name: Configure sensitive data
  template:
    src: secure_template.j2
    dest: /etc/app/config
  vars:
    api_key: "secret123"
  no_log: true

Variable Debugging

Debug Module

- name: Debug variables
  debug:
    var: variable_name
    verbosity: 2

- name: Debug complex structure
  debug:
    msg: |
      Host: {{ inventory_hostname }}
      OS: {{ ansible_os_family }}
      Memory: {{ ansible_memtotal_mb }}

Variable Inspection

- name: Dump all variables
  debug:
    msg: |
      All variables:
      {{ vars | to_nice_yaml }}

Best Practices

Variable Naming

# Good names
app_version: "1.0.0"
http_port: 80
max_connections: 1000

# Avoid
v: "1.0.0"
port: 80
max: 1000

Variable Organization

# Group related variables
database:
  host: localhost
  port: 5432
  name: myapp
  user: admin
  max_connections: 100

application:
  name: myapp
  version: 1.0.0
  environment: production
  features:
    logging: true
    monitoring: true

Variable Documentation

# vars/main.yml
---
# Database configuration
# Required for application database connection
db_host: localhost      # Database server hostname
db_port: 5432          # PostgreSQL default port
db_name: myapp         # Application database name

# Application settings
app_name: myapp        # Application identifier
app_port: 8080         # Application listening port
debug_mode: false      # Enable debug logging