Ansible Generator
Overview
Generate production-ready Ansible resources (playbooks, roles, task files, inventory files, project configs) following current best practices, naming conventions, and security standards. All generated resources are validated using the devops-skills:ansible-validator skill before delivery.
Core Capabilities
All capabilities follow the same validation loop: generate → invoke devops-skills:ansible-validator → fix errors → re-validate → present output. See Validation Workflow for full details.
1. Generate Playbooks
Process:
- Clarify hosts, privileges, OS
- Read
references/best-practices.md and references/module-patterns.md
- Use
assets/templates/playbook/basic_playbook.yml as structural reference
- Generate following mandatory standards (see Mandatory Standards)
Example structure:
---
# Playbook: <title>
# Description: <what it does>
# Requirements: Ansible 2.10+, <OS>
# Variables:
# - <var_name>: <description> (default: <value>)
# Usage: ansible-playbook -i inventory/<env> <playbook>.yml
- name: <Verb phrase describing the play>
hosts: <group>
become: true
gather_facts: true
vars:
app_port: 8080
pre_tasks:
- name: <Setup steps>
# ...
tasks:
- name: <Verb-first task name>
ansible.builtin.<module>:
# parameters
tags: [<tag1>, <tag2>]
post_tasks:
- name: <Verification steps>
# ...
handlers:
- name: <Handler name>
ansible.builtin.service:
name: <service>
state: reloaded
2. Generate Roles
Process:
- Clarify role purpose and scope
- Copy and customize the full role structure from
assets/templates/role/:
tasks/main.yml, handlers/main.yml, templates/, files/
vars/main.yml, vars/Debian.yml, vars/RedHat.yml
defaults/main.yml, meta/main.yml, meta/argument_specs.yml (Ansible 2.11+), README.md
- Replace all
[PLACEHOLDERS]: [ROLE_NAME], [role_name], [PLAYBOOK_DESCRIPTION], [package_name], [service_name], [default_port]
- Prefix all role variables with the role name (e.g.,
nginx_port, nginx_worker_processes)
- Use
include_vars for OS-specific variables
meta/argument_specs.yml enables automatic variable validation (Ansible 2.11+).
3. Generate Task Files
Process:
- Define the operation
- Reference
references/module-patterns.md for module usage
- Generate with: verb-first names, FQCN modules, idempotency checks, tags
See assets/templates/ for full task file examples (e.g., database backup, user management).
4. Generate Inventory Files
Process:
- Understand infrastructure topology
- Use
assets/templates/inventory/ as reference:
hosts — main inventory (INI for simple; YAML for complex hierarchies)
group_vars/all.yml, group_vars/[groupname].yml, host_vars/[hostname].yml
- Organize hosts into logical groups (functional, environment, geographic)
- Define variables at appropriate levels: all → group → host
Dynamic inventory (cloud): Use provider plugins configured from references/module-patterns.md:
- AWS EC2:
plugin: amazon.aws.aws_ec2
- Azure:
plugin: azure.azcollection.azure_rm
5. Generate Project Configuration Files
Use templates from assets/templates/project/:
ansible.cfg — forks, timeout, paths
requirements.yml — collections and roles dependencies
.ansible-lint — lint rules
6. Handling Custom Modules and Collections
When a user mentions a non-builtin collection (e.g., kubernetes.core, amazon.aws, community.docker):
- Search for current documentation:
"ansible [collection.name] [module] latest documentation examples"
- If Context7 MCP is available: Use
mcp__context7__resolve-library-id then mcp__context7__get-library-docs
- Generate using discovered info: correct FQCN, current parameters, collection install instructions
Include installation instructions in comments:
# Requirements:
# - ansible-galaxy collection install kubernetes.core:2.4.0
# or in requirements.yml:
# collections:
# - name: kubernetes.core
# version: "2.4.0"
Mandatory Standards
All generated resources must follow these standards. See references/best-practices.md for full details and rationale.
Key rules at a glance:
| Standard |
Correct |
Incorrect |
| FQCN |
ansible.builtin.copy |
copy |
| Booleans |
true/false |
yes/no |
| RHEL packages |
ansible.builtin.dnf |
ansible.builtin.yum |
| Secrets |
no_log: true |
plain logging |
| File perms |
'0644' configs, '0600' secrets |
world-writable |
Builtin Fallback Pattern
When validation fails due to missing collections, rewrite using builtins:
# Preferred (requires community.postgresql):
# - community.postgresql.postgresql_db: {name: mydb, state: present}
# Builtin fallback:
- 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
Common Patterns
Multi-OS Support
- name: Install nginx (Debian/Ubuntu)
ansible.builtin.apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: Install nginx (RHEL 8+)
ansible.builtin.dnf:
name: nginx
state: present
when: ansible_os_family == "RedHat"
Async Long-Running Tasks
- 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
Validation Workflow
Every generated resource must be validated before presenting to the user.
- Generate the Ansible file
- Invoke
devops-skills:ansible-validator
- If validation fails → fix errors → re-validate
- If validation passes → present using the required output format
Skip validation only when: generating partial snippets, documentation examples, or when the user explicitly requests to skip.
Required Output Format
## Generated [Resource Type]: [Name]
**Validation Status:** ✅ All checks passed
- YAML syntax: Passed
- Ansible syntax: Passed
- Ansible lint: Passed
**Summary:**
- [What was generated and key decisions]
**Usage:**
```bash
[Exact command]
```
**Prerequisites:**
- [Required collections, system requirements]
Anti-Patterns
NEVER use gather_facts: true by default for large inventories
- WHY: Fact gathering adds 2-5 seconds per host at connection time; for playbooks targeting hundreds of hosts this significantly increases total runtime for plays that do not need facts.
- BAD: Relying on the default
gather_facts behaviour in every play, including utility plays that never reference ansible_* variables.
- GOOD: Set
gather_facts: false globally in ansible.cfg and enable it per-play only when facts are actually needed (conditionals, templates using ansible_os_family, etc.).
NEVER store secrets in group_vars/ plaintext files
- WHY: Any plaintext password or API key committed to
group_vars/ is permanently exposed in source control history, even after deletion.
- BAD:
ansible_become_password: mypassword in group_vars/all.yml committed to the repository.
- GOOD: Use Ansible Vault (
ansible-vault encrypt_string) or an external secrets manager (HashiCorp Vault, AWS Secrets Manager) and reference values via lookup plugins.
NEVER use the shell or command module when a dedicated module exists
- WHY:
shell and command bypass idempotency guarantees, built-in error handling, and change detection that dedicated modules provide; they also resist linting and security scanning.
- BAD:
ansible.builtin.shell: pip install requests instead of using the pip module.
- GOOD:
ansible.builtin.pip: name: requests state: present — use the purpose-built module so Ansible can detect and report actual state changes.
NEVER write tasks without name: fields
- WHY: Unnamed tasks produce unreadable playbook output and make debugging nearly impossible when a play contains many tasks; they also fail
ansible-lint name rules.
- BAD:
- apt: name=nginx state=present with no name: field.
- GOOD: Always prefix every task with a descriptive
name:, e.g., - name: Install nginx web server.
NEVER use ignore_errors: true as a general exception handler
- WHY:
ignore_errors: true silently swallows all failures and lets the playbook continue in a potentially broken state, masking errors that affect downstream tasks.
- BAD:
ignore_errors: true on a package installation task where failure means the service cannot start.
- GOOD: Use
failed_when with specific conditions to define expected failure states, or use block/rescue/always for structured error handling with recovery logic.
References
References (read at generation start)
references/best-practices.md — directory structures, naming conventions, security, performance, common pitfalls
references/module-patterns.md — module usage patterns, copy-paste examples for all common modules
Assets (structural templates)
assets/templates/playbook/basic_playbook.yml — playbook structure reference
assets/templates/role/* — role directory structure and variable conventions
assets/templates/inventory/* — host grouping and group_vars/host_vars patterns
assets/templates/project/* — ansible.cfg, requirements.yml, .ansible-lint
Template usage: Review structure → generate following the same pattern → replace [PLACEHOLDERS] → customize for requirements → remove inapplicable sections → validate.
1---2name: ansible-generator3description: Generates, validates, and refactors production-ready Ansible playbooks, roles, task files, and inventory configurations following current best practices. Use when the user asks to create, build, or generate Ansible automation, YAML playbooks, infrastructure as code, configuration management files, DevOps roles, or .yml files for Ansible — including requests like "create a playbook to...", "build a role for...", "generate an inventory for...", or "set up Ansible to automate...". Automatically validates all output using the devops-skills:ansible-validator skill.4---56# Ansible Generator78## Overview910Generate production-ready Ansible resources (playbooks, roles, task files, inventory files, project configs) following current best practices, naming conventions, and security standards. All generated resources are validated using the `devops-skills:ansible-validator` skill before delivery.1112## Core Capabilities1314> **All capabilities follow the same validation loop:** generate → invoke `devops-skills:ansible-validator` → fix errors → re-validate → present output. See [Validation Workflow](#validation-workflow) for full details.1516### 1. Generate Playbooks1718**Process:**191. Clarify hosts, privileges, OS202. Read `references/best-practices.md` and `references/module-patterns.md`213. Use `assets/templates/playbook/basic_playbook.yml` as structural reference224. Generate following mandatory standards (see [Mandatory Standards](#mandatory-standards))2324**Example structure:**25```yaml26---27# Playbook: <title>28# Description: <what it does>29# Requirements: Ansible 2.10+, <OS>30# Variables:31# - <var_name>: <description> (default: <value>)32# Usage: ansible-playbook -i inventory/<env> <playbook>.yml3334- name: <Verb phrase describing the play>35 hosts: <group>36 become: true37 gather_facts: true38 vars:39 app_port: 80804041 pre_tasks:42 - name: <Setup steps>43 # ...4445 tasks:46 - name: <Verb-first task name>47 ansible.builtin.<module>:48 # parameters49 tags: [<tag1>, <tag2>]5051 post_tasks:52 - name: <Verification steps>53 # ...5455 handlers:56 - name: <Handler name>57 ansible.builtin.service:58 name: <service>59 state: reloaded60```6162---6364### 2. Generate Roles6566**Process:**671. Clarify role purpose and scope682. Copy and customize the full role structure from `assets/templates/role/`:69 - `tasks/main.yml`, `handlers/main.yml`, `templates/`, `files/`70 - `vars/main.yml`, `vars/Debian.yml`, `vars/RedHat.yml`71 - `defaults/main.yml`, `meta/main.yml`, `meta/argument_specs.yml` (Ansible 2.11+), `README.md`723. Replace all `[PLACEHOLDERS]`: `[ROLE_NAME]`, `[role_name]`, `[PLAYBOOK_DESCRIPTION]`, `[package_name]`, `[service_name]`, `[default_port]`734. Prefix all role variables with the role name (e.g., `nginx_port`, `nginx_worker_processes`)745. Use `include_vars` for OS-specific variables7576**`meta/argument_specs.yml`** enables automatic variable validation (Ansible 2.11+).7778---7980### 3. Generate Task Files8182**Process:**831. Define the operation842. Reference `references/module-patterns.md` for module usage853. Generate with: verb-first names, FQCN modules, idempotency checks, tags8687See `assets/templates/` for full task file examples (e.g., database backup, user management).8889---9091### 4. Generate Inventory Files9293**Process:**941. Understand infrastructure topology952. Use `assets/templates/inventory/` as reference:96 - `hosts` — main inventory (INI for simple; YAML for complex hierarchies)97 - `group_vars/all.yml`, `group_vars/[groupname].yml`, `host_vars/[hostname].yml`983. Organize hosts into logical groups (functional, environment, geographic)994. Define variables at appropriate levels: all → group → host100101**Dynamic inventory (cloud):** Use provider plugins configured from `references/module-patterns.md`:102- AWS EC2: `plugin: amazon.aws.aws_ec2`103- Azure: `plugin: azure.azcollection.azure_rm`104105---106107### 5. Generate Project Configuration Files108109Use templates from `assets/templates/project/`:110- `ansible.cfg` — forks, timeout, paths111- `requirements.yml` — collections and roles dependencies112- `.ansible-lint` — lint rules113114---115116### 6. Handling Custom Modules and Collections117118When a user mentions a non-builtin collection (e.g., `kubernetes.core`, `amazon.aws`, `community.docker`):1191201. **Search for current documentation:**121 ```122 "ansible [collection.name] [module] latest documentation examples"123 ```1242. **If Context7 MCP is available:** Use `mcp__context7__resolve-library-id` then `mcp__context7__get-library-docs`1253. **Generate using discovered info:** correct FQCN, current parameters, collection install instructions126127**Include installation instructions in comments:**128```yaml129# Requirements:130# - ansible-galaxy collection install kubernetes.core:2.4.0131# or in requirements.yml:132# collections:133# - name: kubernetes.core134# version: "2.4.0"135```136137---138139## Mandatory Standards140141All generated resources must follow these standards. See `references/best-practices.md` for full details and rationale.142143**Key rules at a glance:**144145| Standard | Correct | Incorrect |146|---|---|---|147| FQCN | `ansible.builtin.copy` | `copy` |148| Booleans | `true`/`false` | `yes`/`no` |149| RHEL packages | `ansible.builtin.dnf` | `ansible.builtin.yum` |150| Secrets | `no_log: true` | plain logging |151| File perms | `'0644'` configs, `'0600'` secrets | world-writable |152153### Builtin Fallback Pattern154155When validation fails due to missing collections, rewrite using builtins:156157```yaml158# Preferred (requires community.postgresql):159# - community.postgresql.postgresql_db: {name: mydb, state: present}160161# Builtin fallback:162- name: Check if database exists163 ansible.builtin.command:164 cmd: psql -tAc "SELECT 1 FROM pg_database WHERE datname='mydb'"165 become: true166 become_user: postgres167 register: db_check168 changed_when: false169170- name: Create database171 ansible.builtin.command:172 cmd: psql -c "CREATE DATABASE mydb"173 become: true174 become_user: postgres175 when: db_check.stdout != "1"176 changed_when: true177```178179---180181## Common Patterns182183### Multi-OS Support184185```yaml186- name: Install nginx (Debian/Ubuntu)187 ansible.builtin.apt:188 name: nginx189 state: present190 when: ansible_os_family == "Debian"191192- name: Install nginx (RHEL 8+)193 ansible.builtin.dnf:194 name: nginx195 state: present196 when: ansible_os_family == "RedHat"197```198199### Async Long-Running Tasks200201```yaml202- name: Run database migration203 ansible.builtin.command: /opt/app/migrate.sh204 async: 3600205 poll: 0206 register: migration207208- name: Check migration status209 ansible.builtin.async_status:210 jid: "{{ migration.ansible_job_id }}"211 register: job_result212 until: job_result.finished213 retries: 360214 delay: 10215```216217---218219## Validation Workflow220221**Every generated resource must be validated before presenting to the user.**2222231. Generate the Ansible file2242. Invoke `devops-skills:ansible-validator`2253. If validation fails → fix errors → re-validate2264. If validation passes → present using the required output format227228**Skip validation only when:** generating partial snippets, documentation examples, or when the user explicitly requests to skip.229230### Required Output Format231232````markdown233## Generated [Resource Type]: [Name]234235**Validation Status:** ✅ All checks passed236- YAML syntax: Passed237- Ansible syntax: Passed238- Ansible lint: Passed239240**Summary:**241- [What was generated and key decisions]242243**Usage:**244```bash245[Exact command]246```247248**Prerequisites:**249- [Required collections, system requirements]250````251252---253254## Anti-Patterns255256### NEVER use `gather_facts: true` by default for large inventories257258- **WHY**: Fact gathering adds 2-5 seconds per host at connection time; for playbooks targeting hundreds of hosts this significantly increases total runtime for plays that do not need facts.259- **BAD**: Relying on the default `gather_facts` behaviour in every play, including utility plays that never reference `ansible_*` variables.260- **GOOD**: Set `gather_facts: false` globally in `ansible.cfg` and enable it per-play only when facts are actually needed (conditionals, templates using `ansible_os_family`, etc.).261262### NEVER store secrets in `group_vars/` plaintext files263264- **WHY**: Any plaintext password or API key committed to `group_vars/` is permanently exposed in source control history, even after deletion.265- **BAD**: `ansible_become_password: mypassword` in `group_vars/all.yml` committed to the repository.266- **GOOD**: Use Ansible Vault (`ansible-vault encrypt_string`) or an external secrets manager (HashiCorp Vault, AWS Secrets Manager) and reference values via lookup plugins.267268### NEVER use the `shell` or `command` module when a dedicated module exists269270- **WHY**: `shell` and `command` bypass idempotency guarantees, built-in error handling, and change detection that dedicated modules provide; they also resist linting and security scanning.271- **BAD**: `ansible.builtin.shell: pip install requests` instead of using the `pip` module.272- **GOOD**: `ansible.builtin.pip: name: requests state: present` — use the purpose-built module so Ansible can detect and report actual state changes.273274### NEVER write tasks without `name:` fields275276- **WHY**: Unnamed tasks produce unreadable playbook output and make debugging nearly impossible when a play contains many tasks; they also fail `ansible-lint` name rules.277- **BAD**: `- apt: name=nginx state=present` with no `name:` field.278- **GOOD**: Always prefix every task with a descriptive `name:`, e.g., `- name: Install nginx web server`.279280### NEVER use `ignore_errors: true` as a general exception handler281282- **WHY**: `ignore_errors: true` silently swallows all failures and lets the playbook continue in a potentially broken state, masking errors that affect downstream tasks.283- **BAD**: `ignore_errors: true` on a package installation task where failure means the service cannot start.284- **GOOD**: Use `failed_when` with specific conditions to define expected failure states, or use `block/rescue/always` for structured error handling with recovery logic.285286## References287288### References (read at generation start)289290- `references/best-practices.md` — directory structures, naming conventions, security, performance, common pitfalls291- `references/module-patterns.md` — module usage patterns, copy-paste examples for all common modules292293### Assets (structural templates)294295- `assets/templates/playbook/basic_playbook.yml` — playbook structure reference296- `assets/templates/role/*` — role directory structure and variable conventions297- `assets/templates/inventory/*` — host grouping and group_vars/host_vars patterns298- `assets/templates/project/*` — `ansible.cfg`, `requirements.yml`, `.ansible-lint`299300**Template usage:** Review structure → generate following the same pattern → replace `[PLACEHOLDERS]` → customize for requirements → remove inapplicable sections → validate.