ansible-fundamentals
This skill should be used when writing Ansible playbooks, creating Ansible tasks, running ansible-playbook commands, selecting Ansible modules, or working with Ansible collections. Provides golden rules, FQCN requirements, module selection guidance, and execution patterns using uv run.
$ 설치
git clone https://github.com/basher83/lunar-claude /tmp/lunar-claude && cp -r /tmp/lunar-claude/plugins/infrastructure/ansible-workflows/skills/ansible-fundamentals ~/.claude/skills/lunar-claude// tip: Run this command in your terminal to install the skill
name: ansible-fundamentals description: > This skill should be used when writing Ansible playbooks, creating Ansible tasks, running ansible-playbook commands, selecting Ansible modules, or working with Ansible collections. Provides golden rules, FQCN requirements, module selection guidance, and execution patterns using uv run.
Ansible Fundamentals
Core principles and golden rules for writing production-quality Ansible automation.
Golden Rules
These rules apply to ALL Ansible code in this repository:
-
Use
uv runprefix - Execute all Ansible commands through uv:uv run ansible-playbook playbooks/my-playbook.yml uv run ansible-lint uv run ansible-galaxy collection install -r requirements.yml -
Fully Qualified Collection Names (FQCN) - Avoid short module names:
# CORRECT - name: Install package ansible.builtin.apt: name: nginx state: present # WRONG - deprecated short names - name: Install package apt: name: nginx -
Control command/shell modules - Add
changed_whenandfailed_when:- name: Check if service exists ansible.builtin.command: systemctl status myservice register: service_check changed_when: false failed_when: false -
Use
set -euo pipefail- In all shell scripts and shell module calls:- name: Run pipeline command ansible.builtin.shell: | set -euo pipefail cat file.txt | grep pattern | wc -l args: executable: /bin/bash -
Tag sensitive tasks - Use
no_log: truefor secrets:- name: Set database password ansible.builtin.command: set-password {{ db_password }} no_log: true -
Idempotency first - Check before create, verify after.
-
Descriptive task names - Start with action verbs (Ensure, Configure, Install, Create).
Module Selection Guide
Decision Matrix
| Need | Use | Why |
|---|---|---|
| Install packages | ansible.builtin.apt/yum/dnf | Native modules handle state |
| Manage files | ansible.builtin.copy/template/file | Idempotent by default |
| Edit config lines | ansible.builtin.lineinfile | Surgical edits, not full replace |
| Run commands | ansible.builtin.command | When no native module exists |
| Need shell features | ansible.builtin.shell | Pipes, redirects, globs |
| Manage services | ansible.builtin.systemd/service | State management built-in |
| Manage users | ansible.builtin.user | Cross-platform, idempotent |
Prefer Native Modules
Native modules provide:
- Built-in idempotency (no need for
changed_when) - Better error handling
- Cross-platform compatibility
- Clear documentation
# PREFER native module
- name: Create user
ansible.builtin.user:
name: deploy
groups: docker
state: present
# AVOID command when module exists
- name: Create user
ansible.builtin.command: useradd -G docker deploy
# Requires: changed_when, failed_when, idempotency logic
When Command/Shell is Acceptable
Use command or shell modules when:
- No native module exists for the operation
- Interacting with vendor CLI tools (pvecm, pveceph, kubectl)
- Running one-off scripts
Add proper controls:
- name: Create Proxmox API token
ansible.builtin.command: >
pveum user token add {{ username }}@pam {{ token_name }}
register: token_result
changed_when: "'already exists' not in token_result.stderr"
failed_when:
- token_result.rc != 0
- "'already exists' not in token_result.stderr"
no_log: true
Collections in Use
This repository uses these Ansible collections:
| Collection | Purpose | Example Modules |
|---|---|---|
ansible.builtin | Core functionality | copy, template, command, user |
ansible.posix | POSIX systems | authorized_key, synchronize |
community.general | General utilities | interfaces_file, ini_file |
community.proxmox | Proxmox VE | proxmox_vm, proxmox_kvm |
infisical.vault | Secrets management | read_secrets |
community.docker | Docker management | docker_container, docker_image |
Installing Collections
# Install from requirements
cd ansible && uv run ansible-galaxy collection install -r requirements.yml
# Install specific collection
uv run ansible-galaxy collection install community.proxmox
Common Execution Patterns
Running Playbooks
# Basic execution
uv run ansible-playbook playbooks/my-playbook.yml
# With extra variables
uv run ansible-playbook playbooks/create-vm.yml \
-e "vm_name=docker-01" \
-e "vm_memory=4096"
# Limit to specific hosts
uv run ansible-playbook playbooks/update.yml --limit proxmox
# Check mode (dry run)
uv run ansible-playbook playbooks/deploy.yml --check --diff
# With tags
uv run ansible-playbook playbooks/setup.yml --tags "network,storage"
Linting
# Run ansible-lint
mise run ansible-lint
# Or directly
uv run ansible-lint ansible/playbooks/
Task Naming Conventions
Use descriptive names with action verbs:
| Verb | Use When |
|---|---|
| Ensure | Verifying state exists |
| Configure | Modifying settings |
| Install | Adding packages |
| Create | Making new resources |
| Remove | Deleting resources |
| Deploy | Releasing applications |
| Update | Modifying existing resources |
Examples:
- name: Ensure Docker is installed
- name: Configure SSH security settings
- name: Create admin user account
- name: Deploy application configuration
Variable Naming
Use snake_case with descriptive names:
# GOOD - clear, descriptive
proxmox_api_user: terraform@pam
docker_compose_version: "2.24.0"
vm_memory_mb: 4096
# BAD - vague, abbreviated
pve_usr: terraform@pam
dc_ver: "2.24.0"
mem: 4096
Quick Reference Commands
# Lint all Ansible files
mise run ansible-lint
# Run playbook with secrets from Infisical
cd ansible && uv run ansible-playbook playbooks/my-playbook.yml
# Check syntax
uv run ansible-playbook --syntax-check playbooks/my-playbook.yml
# List hosts in inventory
uv run ansible-inventory --list
# Test connection
uv run ansible all -m ping
Common Anti-Patterns
Missing FQCN
# BAD
- name: Copy file
copy:
src: file.txt
dest: /tmp/
# GOOD
- name: Copy file
ansible.builtin.copy:
src: file.txt
dest: /tmp/
Uncontrolled Commands
# BAD - always shows changed, no error handling
- name: Check status
ansible.builtin.command: systemctl status app
# GOOD
- name: Check status
ansible.builtin.command: systemctl status app
register: status_check
changed_when: false
failed_when: false
Using shell When command Suffices
# BAD - shell not needed
- name: List files
ansible.builtin.shell: ls -la /tmp
# GOOD - command is sufficient
- name: List files
ansible.builtin.command: ls -la /tmp
changed_when: false
Missing no_log on Secrets
# BAD - password in logs
- name: Set password
ansible.builtin.command: set-password {{ password }}
# GOOD
- name: Set password
ansible.builtin.command: set-password {{ password }}
no_log: true
Related Skills
- ansible-idempotency - Detailed changed_when/failed_when patterns
- ansible-secrets - Infisical integration and security
- ansible-proxmox - Proxmox-specific module selection
- ansible-error-handling - Block/rescue, retry patterns
Repository
