ansible-workflow
Ansible automation workflow guidelines. Activate when working with Ansible playbooks, ansible-playbook, inventory files (.yml, .ini), or Ansible-specific patterns.
$ Instalar
git clone https://github.com/ilude/claude-code-config /tmp/claude-code-config && cp -r /tmp/claude-code-config/skills/ansible-workflow ~/.claude/skills/claude-code-config// tip: Run this command in your terminal to install the skill
name: ansible-workflow description: Ansible automation workflow guidelines. Activate when working with Ansible playbooks, ansible-playbook, inventory files (.yml, .ini), or Ansible-specific patterns. location: user
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in RFC 2119.
Ansible Workflow
Tool Grid
| Task | Tool | Command |
|---|---|---|
| Lint | ansible-lint | ansible-lint |
| YAML lint | yamllint | yamllint . |
| Syntax check | ansible | ansible-playbook --syntax-check |
| Dry run | ansible | ansible-playbook --check |
| Run | ansible | ansible-playbook playbook.yml |
| Test roles | molecule | molecule test |
| Encrypt | sops | sops -e secrets.yml |
| Decrypt | sops | sops -d secrets.yml |
Runtime Requirements
- Ansible Core 2.18+ with Python 3.12+
- ansible-lint and yamllint installed
- SOPS for secrets management (RECOMMENDED over ansible-vault for GitOps)
- Molecule + docker driver for role testing
Code Standards
FQCN Requirement
All module names MUST use Fully Qualified Collection Names (FQCN):
# CORRECT
- name: Copy configuration file
ansible.builtin.copy:
src: app.conf
dest: /etc/app/app.conf
# INCORRECT - DO NOT USE
- name: Copy configuration file
copy:
src: app.conf
dest: /etc/app/app.conf
Linting
All playbooks and roles MUST pass linting before commit:
# Run both linters
ansible-lint && yamllint .
Configuration templates available in assets/:
.ansible-lint.template- Production profile with strict mode.yamllint.template- YAML linting with 120 char lines
Sensitive Data
Tasks handling sensitive data MUST use no_log: true:
- name: Set database password
ansible.builtin.shell: |
mysql -u root -p'{{ db_root_password }}' -e "SET PASSWORD..."
no_log: true
- name: Create API token
ansible.builtin.uri:
url: "{{ api_endpoint }}/tokens"
headers:
Authorization: "Bearer {{ admin_token }}"
no_log: true
register: token_result
Secrets Management
SOPS (RECOMMENDED for GitOps)
SOPS is RECOMMENDED over ansible-vault for GitOps workflows:
# .sops.yaml
creation_rules:
- path_regex: .*vars/secrets\.yml$
age: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Encrypt
sops -e vars/secrets.yml > vars/secrets.enc.yml
# Decrypt inline during playbook
sops -d vars/secrets.enc.yml | ansible-playbook -e @/dev/stdin playbook.yml
ansible-vault (Legacy)
When ansible-vault is required:
# Encrypt variable file
ansible-vault encrypt group_vars/prod/vault.yml
# Run with vault
ansible-playbook --ask-vault-pass playbook.yml
Project Structure
Environment-Based Inventory
inventories/
├── prod/
│ ├── hosts.yml
│ ├── group_vars/
│ │ ├── all.yml
│ │ ├── webservers.yml
│ │ └── databases.yml
│ └── host_vars/
├── staging/
│ ├── hosts.yml
│ └── group_vars/
└── dev/
├── hosts.yml
└── group_vars/
group_vars Organization
Organize group_vars by role name for clarity:
group_vars/
├── all/
│ ├── main.yml # Common variables
│ └── secrets.enc.yml # SOPS-encrypted secrets
├── webservers/
│ ├── nginx.yml # Role: nginx
│ └── ssl.yml # Role: ssl_certificates
└── databases/
├── postgresql.yml # Role: postgresql
└── backup.yml # Role: db_backup
Role Structure
Roles SHOULD be single-purpose:
roles/
├── nginx/ # Web server only
├── ssl_certificates/ # SSL management only
├── postgresql/ # Database only
└── app_deploy/ # Application deployment only
Dynamic Inventories
AWS EC2
# inventories/aws/aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
- us-east-1
- us-west-2
keyed_groups:
- key: tags.Environment
prefix: env
- key: tags.Role
prefix: role
filters:
instance-state-name: running
hostnames:
- private-ip-address
compose:
ansible_host: private_ip_address
Azure RM
# inventories/azure/azure_rm.yml
plugin: azure.azcollection.azure_rm
auth_source: auto
include_vm_resource_groups:
- production-rg
- staging-rg
keyed_groups:
- key: tags.Environment
prefix: env
hostnames:
- private_ipv4_addresses
GCP Compute
# inventories/gcp/gcp_compute.yml
plugin: google.cloud.gcp_compute
projects:
- my-project-id
zones:
- us-central1-a
- us-central1-b
keyed_groups:
- key: labels.environment
prefix: env
hostnames:
- private_ip
Handler Patterns
Proper Handler Usage
# tasks/main.yml
- name: Update nginx configuration
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: Restart nginx
- name: Update SSL certificate
ansible.builtin.copy:
src: "{{ ssl_cert_file }}"
dest: /etc/nginx/ssl/cert.pem
notify:
- Validate nginx config
- Reload nginx
# handlers/main.yml
- name: Validate nginx config
ansible.builtin.command: nginx -t
changed_when: false
- name: Reload nginx
ansible.builtin.systemd:
name: nginx
state: reloaded
- name: Restart nginx
ansible.builtin.systemd:
name: nginx
state: restarted
Handler Execution Order
Handlers execute in definition order, not notification order. Define handlers in logical sequence (validate -> reload -> restart).
Variable Precedence
Ansible variable precedence (highest to lowest):
- Extra vars (
-e "var=value") - Task vars (in task definition)
- Block vars
- Role and include vars
- Set facts / registered vars
- Play vars_files
- Play vars
- Host facts
- Playbook host_vars
- Inventory host_vars
- Playbook group_vars
- Inventory group_vars
- Role defaults
Best Practices
# Use role defaults for safe defaults
# roles/nginx/defaults/main.yml
nginx_worker_processes: auto
nginx_worker_connections: 1024
# Use group_vars for environment-specific overrides
# group_vars/prod/nginx.yml
nginx_worker_connections: 4096
# Use extra vars for one-time overrides only
ansible-playbook playbook.yml -e "nginx_worker_connections=8192"
Molecule Testing
Role Testing Setup
# roles/nginx/molecule/default/molecule.yml
dependency:
name: galaxy
driver:
name: docker
platforms:
- name: instance
image: geerlingguy/docker-${MOLECULE_DISTRO:-rockylinux9}-ansible
pre_build_image: true
privileged: true
command: /usr/sbin/init
provisioner:
name: ansible
verifier:
name: ansible
Running Tests
molecule test # Full test cycle
molecule converge # Apply role
molecule verify # Run verification
molecule destroy # Cleanup
Performance Optimization
ansible.cfg Settings
Use the template at assets/ansible.cfg.template:
forks = 20- Parallel executionpipelining = True- Reduce SSH operationsgathering = smart- Cache factsfact_caching = jsonfile- Persist facts
Task Optimization
# Use async for long-running tasks
- name: Upgrade all packages
ansible.builtin.dnf:
name: "*"
state: latest
async: 600
poll: 10
# Use free strategy for independent tasks
- hosts: all
strategy: free
tasks:
- name: Independent task 1
ansible.builtin.command: /opt/script1.sh
- name: Independent task 2
ansible.builtin.command: /opt/script2.sh
Pre-Commit Checklist
Before committing Ansible code:
-
ansible-lintpasses with no warnings -
yamllint .passes -
ansible-playbook --syntax-checkpasses - All modules use FQCN
- Sensitive tasks have
no_log: true - Secrets encrypted with SOPS (or vault)
- Molecule tests pass for modified roles
- Variables documented in role README
Repository
