Comprehensive toolkit for generating best practice Ansible playbooks, roles, tasks, and inventory files.
Generate production-ready Ansible resources (playbooks, roles, tasks, inventory files) following current best practices, naming conventions, and security standards. All generated resources are automatically validated using the devops-skills:ansible-validator skill to ensure syntax correctness and lint compliance.
Create complete, production-ready playbooks with proper structure, error handling, and idempotency.
When to use:
Process:
assets/templates/playbook/basic_playbook.yml as structural foundationreferences/best-practices.mdreferences/module-patterns.md for correct module usageExample structure:
---
# Playbook: Deploy Web Application
# Description: Deploy nginx web server with SSL
# Requirements:
# - Ansible 2.10+
# - Target hosts: Ubuntu 20.04+
# Variables:
# - app_port: Application port (default: 8080)
# Usage:
# ansible-playbook -i inventory/production deploy_web.yml
- name: Deploy and configure web server
hosts: webservers
become: true
gather_facts: true
vars:
app_port: 8080
nginx_version: latest
pre_tasks:
- name: Update package cache
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
when: ansible_os_family == "Debian"
tasks:
- name: Ensure nginx is installed
ansible.builtin.package:
name: nginx
state: present
tags:
- install
- nginx
- name: Deploy nginx configuration
ansible.builtin.template:
src: templates/nginx.conf.j2
dest: /etc/nginx/nginx.conf
mode: '0644'
backup: true
validate: 'nginx -t -c %s'
notify: Reload nginx
tags:
- configure
post_tasks:
- name: Verify nginx is responding
ansible.builtin.uri:
url: "http://localhost:{{ app_port }}/health"
status_code: 200
register: health_check
until: health_check.status == 200
retries: 5
delay: 10
handlers:
- name: Reload nginx
ansible.builtin.service:
name: nginx
state: reloaded
Create complete role structures with all required components organized following Ansible Galaxy conventions.
When to use:
Process:
assets/templates/role/:
tasks/main.yml - Main task execution logichandlers/main.yml - Event handlers (service restarts, reloads)templates/ - Jinja2 configuration templatesfiles/ - Static files to copyvars/main.yml - Role-specific variables (high priority)vars/Debian.yml and vars/RedHat.yml - OS-specific variablesdefaults/main.yml - Default variables (easily overridable)meta/main.yml - Role metadata and dependenciesREADME.md - Role documentation[PLACEHOLDERS] with actual values:
[ROLE_NAME] - The role name (lowercase with underscores)[role_name] - Variable prefix for role variables[PLAYBOOK_DESCRIPTION] - Description of what the role does[package_name], [service_name] - Actual package/service names[default_port] - Default port numbersinclude_varsRole variable naming convention:
{{ role_name }}_nginx_port, nginx_worker_processes, postgres_max_connectionsCreate focused task files for specific operations that can be included in playbooks or roles.
When to use:
Process:
references/module-patterns.md for correct module usageExample:
---
# Tasks: Database backup operations
- name: Create backup directory
ansible.builtin.file:
path: "{{ backup_dir }}"
state: directory
mode: '0755'
owner: postgres
group: postgres
- name: Dump PostgreSQL database
ansible.builtin.command: >
pg_dump -h {{ db_host }} -U {{ db_user }} -d {{ db_name }}
-f {{ backup_dir }}/{{ db_name }}_{{ ansible_date_time.date }}.sql
environment:
PGPASSWORD: "{{ db_password }}"
no_log: true
changed_when: true
- name: Compress backup file
ansible.builtin.archive:
path: "{{ backup_dir }}/{{ db_name }}_{{ ansible_date_time.date }}.sql"
dest: "{{ backup_dir }}/{{ db_name }}_{{ ansible_date_time.date }}.sql.gz"
format: gz
remove: true
- name: Remove old backups
ansible.builtin.find:
paths: "{{ backup_dir }}"
patterns: "*.sql.gz"
age: "{{ backup_retention_days }}d"
register: old_backups
- name: Delete old backup files
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_backups.files }}"
Create inventory configurations with proper host organization, group hierarchies, and variable management.
When to use:
Process:
assets/templates/inventory/ as foundation:
hosts - Main inventory file (INI or YAML format)group_vars/all.yml - Global variables for all hostsgroup_vars/[groupname].yml - Group-specific variableshost_vars/[hostname].yml - Host-specific variableswebservers, databases, loadbalancersproduction, staging, developmentus-east, eu-west[group:children]Inventory format preference:
Dynamic Inventory (Cloud Environments): For AWS, Azure, GCP, and other cloud providers, use dynamic inventory plugins:
plugin: amazon.aws.aws_ec2 with filters and keyed_groupsplugin: azure.azcollection.azure_rm with resource group filtersreferences/module-patterns.md for detailed examplesWhen to use:
Process:
assets/templates/project/:
ansible.cfg - Project configuration (forks, timeout, paths)requirements.yml - Collections and roles dependencies.ansible-lint - Lint rules for code qualityWhen generating roles, include meta/argument_specs.yml for automatic variable validation:
assets/templates/role/meta/argument_specs.ymlWhen generating Ansible resources that require custom modules, collections, or providers that are not part of ansible.builtin:
Detection:
Process:
Identify the collection/module:
Search for current documentation using WebSearch:
Search query pattern: "ansible [collection.name] [module] [version] documentation examples"
Examples:
- "ansible kubernetes.core k8s module latest documentation"
- "ansible amazon.aws ec2_instance 2024 examples"
- "ansible community.docker docker_container latest documentation"
Analyze search results for:
If Context7 MCP is available:
mcp__context7__resolve-library-idmcp__context7__get-library-docsGenerate resource using discovered information:
kubernetes.core.k8s, not just k8s)Include installation instructions:
# Requirements:
# - ansible-galaxy collection install kubernetes.core:2.4.0
# or in requirements.yml:
# ---
# collections:
# - name: kubernetes.core
# version: "2.4.0"
Example with custom collection:
---
# Playbook: Deploy Kubernetes Resources
# Requirements:
# - Ansible 2.10+
# - Collection: kubernetes.core >= 2.4.0
# - Install: ansible-galaxy collection install kubernetes.core
# Variables:
# - k8s_namespace: Target namespace (default: default)
# - k8s_kubeconfig: Path to kubeconfig (default: ~/.kube/config)
- name: Deploy application to Kubernetes
hosts: localhost
gather_facts: false
vars:
k8s_namespace: production
k8s_kubeconfig: ~/.kube/config
tasks:
- name: Create namespace
kubernetes.core.k8s:
kubeconfig: "{{ k8s_kubeconfig }}"
state: present
definition:
apiVersion: v1
kind: Namespace
metadata:
name: "{{ k8s_namespace }}"
tags:
- namespace
- name: Deploy application
kubernetes.core.k8s:
kubeconfig: "{{ k8s_kubeconfig }}"
state: present
namespace: "{{ k8s_namespace }}"
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:1.0.0
ports:
- containerPort: 8080
tags:
- deployment
CRITICAL: Every generated Ansible resource MUST be validated before presenting to the user.
After generating any Ansible file, immediately invoke the devops-skills:ansible-validator skill:
Skill: devops-skills:ansible-validator
The devops-skills:ansible-validator skill will:
If validation fails:
If validation succeeds, present the result formally:
Required Presentation Format:
## Generated [Resource Type]: [Name]
**Validation Status:** ✅ All checks passed
- YAML syntax: Passed
- Ansible syntax: Passed
- Ansible lint: Passed
**Summary:**
- [Brief description of what was generated]
- [Key features/sections included]
- [Any notable implementation decisions]
**Usage:**
```bash
[Exact command to run the playbook/role]
Prerequisites:
This formal presentation ensures the user clearly understands:
- That validation was successful
- What was generated and why
- How to use the generated resource
- Any prerequisites or dependencies
Only skip validation when:
Reference references/best-practices.md for comprehensive guidelines. Key principles:
FQCN (Fully Qualified Collection Names):
ansible.builtin.copy, community.general.ufwcopy, ufwIdempotency:
state: present/absent declarationscommand/shell when builtin modules existcommand/shell, use creates, removes, or changed_whenNaming:
Security:
no_log: true for sensitive operationsError Handling:
when conditionals for OS-specific tasksregister to capture task resultsfailed_when and changed_when for command modulesvalidate parameter for configuration filesPerformance:
gather_facts: falseupdate_cache with cache_valid_time for package managersDocumentation:
IMPORTANT: Always prefer builtin modules over collection modules when possible. This ensures:
Priority Order:
ansible.builtin.*) - ALWAYS first choice
references/module-patterns.md for builtin alternatives before using collectionsansible.builtin.command with psql instead of community.postgresql.postgresql_db if collection isn't essentialcommunity.*) - Third choicecommand/shell - Only when no module alternative existsWhen validation fails due to missing collections (e.g., "couldn't resolve module/action"):
First, check if a builtin alternative exists:
ansible.builtin.* equivalentscommunity.postgresql.postgresql_db, use ansible.builtin.command with psql commandscommunity.docker.docker_container, use ansible.builtin.command with docker CLIIf collection is required (no builtin alternative):
If validation environment lacks collections:
ansible.builtin.* modules with equivalent CLI commandschanged_when and creates/removes for idempotency with command modulesExample - Builtin fallback for PostgreSQL:
# Preferred (requires community.postgresql collection):
# - name: Create database
# community.postgresql.postgresql_db:
# name: mydb
# state: present
# Builtin fallback (works without collection):
- name: Check if database exists
ansible.builtin.command:
cmd: psql -tAc "SELECT 1 FROM pg_database WHERE datname='mydb'"
become: true
become_user: postgres
register: db_check
changed_when: false
- name: Create database
ansible.builtin.command:
cmd: psql -c "CREATE DATABASE mydb"
become: true
become_user: postgres
when: db_check.stdout != "1"
changed_when: true
IMPORTANT: These reference files should be read at the start of generation to inform implementation decisions. Do not just rely on general knowledge - explicitly read the references to ensure current best practices are applied.
references/best-practices.md - Comprehensive Ansible best practices guide
references/module-patterns.md - Common module usage patterns and examples
Templates serve as structural references showing the expected format and organization. You do NOT need to literally copy and paste them - use them as guides for the correct structure, sections, and patterns.
assets/templates/playbook/basic_playbook.yml - Reference playbook structure
assets/templates/role/* - Reference role directory structure
meta/argument_specs.yml - Role variable validation (Ansible 2.11+)assets/templates/inventory/* - Reference inventory organization
assets/templates/project/* - Reference project configuration
ansible.cfg - Project-level Ansible configurationrequirements.yml - Collections and roles dependencies.ansible-lint - Linting rules configurationHow to use templates:
[PLACEHOLDERS] with actual values appropriate for the taskUser request: "Create a playbook to deploy nginx with SSL"
Process:
✅ Understand requirements:
✅ Reference resources:
references/best-practices.md for playbook structurereferences/module-patterns.md for nginx-related modulesassets/templates/playbook/basic_playbook.yml as base✅ Generate playbook:
✅ Validate:
devops-skills:ansible-validator skill✅ Present to user:
- name: Install nginx (Debian/Ubuntu)
ansible.builtin.apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
# NOTE: For RHEL 8+, use ansible.builtin.dnf instead of yum
# ansible.builtin.yum is deprecated in favor of dnf for modern RHEL/CentOS
- name: Install nginx (RHEL 8+/CentOS 8+)
ansible.builtin.dnf:
name: nginx
state: present
when: ansible_os_family == "RedHat"
- name: Deploy configuration
ansible.builtin.template:
src: app_config.j2
dest: /etc/app/config.yml
mode: '0644'
backup: true
validate: '/usr/bin/app validate %s'
notify: Restart application
- name: Run database migration
ansible.builtin.command: /opt/app/migrate.sh
async: 3600
poll: 0
register: migration
- name: Check migration status
ansible.builtin.async_status:
jid: "{{ migration.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 360
delay: 10
- name: Configure production settings
ansible.builtin.template:
src: production.j2
dest: /etc/app/config.yml
when:
- env == "production"
- ansible_distribution == "Ubuntu"
check_mode: no for tasks that must runBefore presenting any generated Ansible resource to the user, verify all items:
references/best-practices.md and references/module-patterns.mdansible.builtin.*, not bare names)true/false (NOT yes/no) to pass ansible-lintansible.builtin.dnf (NOT ansible.builtin.yum) for modern RHEL/CentOSno_log: true on sensitive tasks, proper file permissionsAfter validation passes, ALWAYS present results in this exact format:
## Generated [Resource Type]: [Name]
**Validation Status:** ✅ All checks passed
- YAML syntax: Passed
- Ansible syntax: Passed
- Ansible lint: Passed
**Summary:**
- [Brief description of what was generated]
- [Key features/sections included]
- [Any notable implementation decisions]
**Usage:**
```bash
[Exact command to run the playbook/role]
Prerequisites:
---
## Summary
Always follow this sequence when generating Ansible resources:
1. **Understand** - Clarify user requirements
2. **Reference** - Check best-practices.md and module-patterns.md
3. **Generate** - Use templates and follow standards (FQCN, idempotency, naming)
4. **Search** - For custom modules/collections, use WebSearch to get current docs
5. **Validate** - ALWAYS use devops-skills:ansible-validator skill
6. **Fix** - Resolve any validation errors
7. **Present** - Deliver validated, production-ready Ansible code
Generate Ansible resources that are:
- ✅ Idempotent and safe to run multiple times
- ✅ Following current best practices and naming conventions
- ✅ Using FQCN for all modules
- ✅ Properly documented with usage instructions
- ✅ Validated and lint-clean
- ✅ Production-ready and maintainable