Ansible Advanced Cheat Sheet

Last Updated: December 24, 2024

Advanced Playbook Patterns

---
- name: Deploy multi-tier application
  hosts: all
  become: yes
  vars:
    app_version: "{{ lookup('env', 'APP_VERSION') | default('latest') }}"
    deploy_env: "{{ ansible_env }}"
  
  pre_tasks:
    - name: Validate prerequisites
      assert:
        that:
          - ansible_version.full is version('2.10', '>=')
          - app_version is defined
        msg: "Requirements not met"

  roles:
    - role: common
      tags: ['common']
    - role: webserver
      tags: ['web']
      when: inventory_hostname in groups['webservers']
    - role: database
      tags: ['db']
      when: inventory_hostname in groups['databases']

  post_tasks:
    - name: Verify deployment
      uri:
        url: "http://{{ ansible_host }}/health"
        status_code: 200
      register: health_check
      until: health_check.status == 200
      retries: 5
      delay: 10

Dynamic Inventory

#!/usr/bin/env python3
# aws_inventory.py
import json
import boto3

def get_inventory():
    ec2 = boto3.client('ec2')
    response = ec2.describe_instances(
        Filters=[{'Name': 'instance-state-name', 'Values': ['running']}]
    )
    
    inventory = {
        '_meta': {'hostvars': {}},
        'all': {'hosts': []},
    }
    
    for reservation in response['Reservations']:
        for instance in reservation['Instances']:
            host = instance['PrivateIpAddress']
            inventory['all']['hosts'].append(host)
            
            # Add tags as groups
            for tag in instance.get('Tags', []):
                if tag['Key'] == 'Group':
                    group = tag['Value']
                    if group not in inventory:
                        inventory[group] = {'hosts': []}
                    inventory[group]['hosts'].append(host)
            
            inventory['_meta']['hostvars'][host] = {
                'instance_id': instance['InstanceId'],
                'instance_type': instance['InstanceType'],
            }
    
    return inventory

if __name__ == '__main__':
    print(json.dumps(get_inventory(), indent=2))

Ansible Vault Best Practices

ansible-vault create secrets.yml
Create encrypted file
ansible-vault encrypt vars.yml
Encrypt existing file
ansible-vault edit secrets.yml
Edit encrypted file
ansible-playbook --vault-password-file=.vault_pass site.yml
Run playbook with vault password file

Custom Modules

#!/usr/bin/python
# library/custom_module.py

from ansible.module_utils.basic import AnsibleModule

def run_module():
    module_args = dict(
        name=dict(type='str', required=True),
        state=dict(type='str', default='present', choices=['present', 'absent']),
    )

    result = dict(
        changed=False,
        message=''
    )

    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    if module.check_mode:
        module.exit_json(**result)

    # Module logic here
    result['changed'] = True
    result['message'] = f"Processed {module.params['name']}"

    module.exit_json(**result)

if __name__ == '__main__':
    run_module()
💡 Pro Tip: Use roles for reusability, implement idempotency in all tasks, and leverage tags for selective execution. Always test playbooks in staging before production.
← Back to DevOps & Cloud | Browse all categories | View all cheat sheets