ansible-testing
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAnsible Testing
Ansible 测试
Testing strategies and ansible-lint configuration for Ansible automation.
Ansible自动化的测试策略与ansible-lint配置。
ansible-lint
ansible-lint
Running Lint
运行代码检查
bash
undefinedbash
undefinedVia mise (recommended)
Via mise (recommended)
mise run ansible-lint
mise run ansible-lint
Directly with uv
Directly with uv
uv run ansible-lint ansible/playbooks/
uv run ansible-lint ansible/playbooks/
Specific file
Specific file
uv run ansible-lint ansible/playbooks/my-playbook.yml
uv run ansible-lint ansible/playbooks/my-playbook.yml
With verbose output
With verbose output
uv run ansible-lint -v ansible/
undefineduv run ansible-lint -v ansible/
undefinedConfiguration File
配置文件
Located at :
ansible/.ansible-lintyaml
---位于:
ansible/.ansible-lintyaml
---Profile: null, min, basic, moderate, safety, shared, production
Profile: null, min, basic, moderate, safety, shared, production
profile: moderate
profile: moderate
Offline mode - don't download Galaxy requirements
Offline mode - don't download Galaxy requirements
offline: true
offline: true
Exclude paths
Exclude paths
exclude_paths:
- .cache/
- .venv/
- .git/
- "*/templates/"
- "*.j2"
- .deprecated/
exclude_paths:
- .cache/
- .venv/
- .git/
- "*/templates/"
- "*.j2"
- .deprecated/
Rules to skip completely
Rules to skip completely
skip_list:
- var-naming[no-role-prefix] # We use descriptive names
- run-once[task] # Safe with our strategy
- command-instead-of-module # CLI tools require command
- yaml[line-length] # Long lines in infra configs
skip_list:
- var-naming[no-role-prefix] # We use descriptive names
- run-once[task] # Safe with our strategy
- command-instead-of-module # CLI tools require command
- yaml[line-length] # Long lines in infra configs
Rules to warn but not fail
Rules to warn but not fail
warn_list:
- fqcn[action-core]
- fqcn[action]
- no-handler
- name[play]
undefinedwarn_list:
- fqcn[action-core]
- fqcn[action]
- no-handler
- name[play]
undefinedCommon Rule Categories
常见规则类别
| Category | Description |
|---|---|
| Fully qualified collection names |
| YAML formatting (indentation, line length) |
| Task/play naming conventions |
| Using command when module exists |
| Missing changed_when on command |
| Missing explicit file permissions |
| 类别 | 描述 |
|---|---|
| 完整限定集合名称 |
| YAML格式(缩进、行长度) |
| 任务/剧本命名规范 |
| 已有模块却使用command |
| 命令缺少changed_when |
| 缺少明确的文件权限 |
Fixing Common Issues
修复常见问题
Missing name on task:
yaml
undefined任务缺少名称:
yaml
undefinedBAD
BAD
- ansible.builtin.apt: name: nginx
- ansible.builtin.apt: name: nginx
GOOD
GOOD
- name: Install nginx ansible.builtin.apt: name: nginx
**Short module name:**
```yaml- name: Install nginx ansible.builtin.apt: name: nginx
**短模块名称:**
```yamlBAD (triggers fqcn warning)
BAD (triggers fqcn warning)
- name: Install package apt: name: nginx
- name: Install package apt: name: nginx
GOOD
GOOD
- name: Install package ansible.builtin.apt: name: nginx
**Using shell instead of command:**
```yaml- name: Install package ansible.builtin.apt: name: nginx
**使用shell而非command:**
```yamlBAD (when no shell features needed)
BAD (when no shell features needed)
- name: List files ansible.builtin.shell: ls -la /tmp
- name: List files ansible.builtin.shell: ls -la /tmp
GOOD
GOOD
- name: List files ansible.builtin.command: ls -la /tmp changed_when: false
**Missing changed_when:**
```yaml- name: List files ansible.builtin.command: ls -la /tmp changed_when: false
**缺少changed_when:**
```yamlBAD (always shows changed)
BAD (always shows changed)
- name: Check status ansible.builtin.command: systemctl status app
- name: Check status ansible.builtin.command: systemctl status app
GOOD
GOOD
- name: Check status ansible.builtin.command: systemctl status app register: status_check changed_when: false failed_when: false
undefined- name: Check status ansible.builtin.command: systemctl status app register: status_check changed_when: false failed_when: false
undefinedSyntax Checking
语法检查
Validate playbook syntax before running:
bash
undefined运行前验证playbook语法:
bash
undefinedCheck syntax only
Check syntax only
uv run ansible-playbook --syntax-check playbooks/my-playbook.yml
uv run ansible-playbook --syntax-check playbooks/my-playbook.yml
Check mode (dry run)
Check mode (dry run)
uv run ansible-playbook playbooks/my-playbook.yml --check
uv run ansible-playbook playbooks/my-playbook.yml --check
Diff mode (show changes)
Diff mode (show changes)
uv run ansible-playbook playbooks/my-playbook.yml --check --diff
undefineduv run ansible-playbook playbooks/my-playbook.yml --check --diff
undefinedIdempotency Testing
幂等性测试
Verify playbooks are idempotent by running twice:
bash
undefined通过运行两次验证playbook的幂等性:
bash
undefinedFirst run - may show changes
First run - may show changes
uv run ansible-playbook playbooks/setup.yml
uv run ansible-playbook playbooks/setup.yml
Second run - should show 0 changes
Second run - should show 0 changes
uv run ansible-playbook playbooks/setup.yml
uv run ansible-playbook playbooks/setup.yml
If second run shows changes, playbook is NOT idempotent
If second run shows changes, playbook is NOT idempotent
undefinedundefinedAutomated Idempotency Check
自动化幂等性检查
bash
#!/bin/bash
set -euo pipefail
PLAYBOOK="$1"
echo "First run..."
uv run ansible-playbook "$PLAYBOOK"
echo "Second run (checking idempotency)..."
OUTPUT=$(uv run ansible-playbook "$PLAYBOOK" 2>&1)
if echo "$OUTPUT" | grep -q "changed=0"; then
echo "✓ Playbook is idempotent"
exit 0
else
echo "✗ Playbook is NOT idempotent"
echo "$OUTPUT" | grep -E "(changed|failed)="
exit 1
fibash
#!/bin/bash
set -euo pipefail
PLAYBOOK="$1"
echo "First run..."
uv run ansible-playbook "$PLAYBOOK"
echo "Second run (checking idempotency)..."
OUTPUT=$(uv run ansible-playbook "$PLAYBOOK" 2>&1)
if echo "$OUTPUT" | grep -q "changed=0"; then
echo "✓ Playbook is idempotent"
exit 0
else
echo "✗ Playbook is NOT idempotent"
echo "$OUTPUT" | grep -E "(changed|failed)="
exit 1
fiIntegration Testing
集成测试
Test Against Real Infrastructure
针对真实基础设施测试
bash
undefinedbash
undefinedLimit to test hosts
Limit to test hosts
uv run ansible-playbook playbooks/deploy.yml --limit test_hosts
uv run ansible-playbook playbooks/deploy.yml --limit test_hosts
With verbose output
With verbose output
uv run ansible-playbook playbooks/deploy.yml --limit test_hosts -vv
undefineduv run ansible-playbook playbooks/deploy.yml --limit test_hosts -vv
undefinedPre-flight Validation
预运行验证
Add validation tasks at playbook start:
yaml
---
- name: Deploy with validation
hosts: all
become: true
pre_tasks:
- name: Validate target environment
ansible.builtin.assert:
that:
- ansible_distribution == "Debian"
- ansible_distribution_major_version | int >= 11
fail_msg: "Requires Debian 11+"
- name: Check connectivity
ansible.builtin.ping:
- name: Verify disk space
ansible.builtin.assert:
that:
- ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first > 1073741824
fail_msg: "Insufficient disk space"在playbook开头添加验证任务:
yaml
---
- name: Deploy with validation
hosts: all
become: true
pre_tasks:
- name: Validate target environment
ansible.builtin.assert:
that:
- ansible_distribution == "Debian"
- ansible_distribution_major_version | int >= 11
fail_msg: "Requires Debian 11+"
- name: Check connectivity
ansible.builtin.ping:
- name: Verify disk space
ansible.builtin.assert:
that:
- ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first > 1073741824
fail_msg: "Insufficient disk space"Test Playbook Pattern
测试Playbook模式
Create test playbooks for validation:
yaml
undefined创建用于验证的测试playbook:
yaml
undefinedplaybooks/test-role.yml
playbooks/test-role.yml
-
name: Test role functionality hosts: test_hosts become: truevars: test_mode: trueroles:
- role: my_role
tasks:-
name: Verify service is running ansible.builtin.systemd: name: myservice register: service_status failed_when: service_status.status.ActiveState != "active"
-
name: Verify config file exists ansible.builtin.stat: path: /etc/myservice/config.yml register: config_stat failed_when: not config_stat.stat.exists
-
name: Verify port is listening ansible.builtin.wait_for: port: 8080 timeout: 10
undefined-
name: Test role functionality hosts: test_hosts become: truevars: test_mode: trueroles:
- role: my_role
tasks:-
name: Verify service is running ansible.builtin.systemd: name: myservice register: service_status failed_when: service_status.status.ActiveState != "active"
-
name: Verify config file exists ansible.builtin.stat: path: /etc/myservice/config.yml register: config_stat failed_when: not config_stat.stat.exists
-
name: Verify port is listening ansible.builtin.wait_for: port: 8080 timeout: 10
undefinedCI/CD Integration
CI/CD集成
GitHub Actions
GitHub Actions
yaml
name: Ansible Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Install uv
run: pip install uv
- name: Install dependencies
run: uv sync
- name: Run ansible-lint
run: uv run ansible-lint ansible/yaml
name: Ansible Lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Install uv
run: pip install uv
- name: Install dependencies
run: uv sync
- name: Run ansible-lint
run: uv run ansible-lint ansible/Debugging Playbooks
调试Playbook
Verbose Output
详细输出
bash
undefinedbash
undefinedIncrease verbosity
Increase verbosity
uv run ansible-playbook playbook.yml -v # Basic
uv run ansible-playbook playbook.yml -vv # More detail
uv run ansible-playbook playbook.yml -vvv # Connection debugging
uv run ansible-playbook playbook.yml -vvvv # Maximum detail
undefineduv run ansible-playbook playbook.yml -v # Basic
uv run ansible-playbook playbook.yml -vv # More detail
uv run ansible-playbook playbook.yml -vvv # Connection debugging
uv run ansible-playbook playbook.yml -vvvv # Maximum detail
undefinedDebug Tasks
调试任务
yaml
- name: Debug variable value
ansible.builtin.debug:
var: my_variable
- name: Debug with message
ansible.builtin.debug:
msg: "The value is {{ my_variable }}"
- name: Debug registered result
ansible.builtin.debug:
var: command_result
when: ansible_verbosity > 0yaml
- name: Debug variable value
ansible.builtin.debug:
var: my_variable
- name: Debug with message
ansible.builtin.debug:
msg: "The value is {{ my_variable }}"
- name: Debug registered result
ansible.builtin.debug:
var: command_result
when: ansible_verbosity > 0Step Mode
分步模式
bash
undefinedbash
undefinedPause after each task
Pause after each task
uv run ansible-playbook playbook.yml --step
undefineduv run ansible-playbook playbook.yml --step
undefinedLint Profiles
代码检查级别
Choose appropriate profile based on needs:
| Profile | Strictness | Use Case |
|---|---|---|
| Lowest | Legacy code, quick fixes |
| Low | Development |
| Medium | General infrastructure |
| High | Security-sensitive |
| Highest | Production deployments |
根据需求选择合适的级别:
| 级别 | 严格程度 | 使用场景 |
|---|---|---|
| 最低 | 遗留代码、快速修复 |
| 低 | 开发环境 |
| 中等 | 通用基础设施 |
| 高 | 安全敏感场景 |
| 最高 | 生产环境部署 |
Additional Resources
额外资源
For detailed testing patterns and techniques, consult:
- - ansible-lint configuration, integration testing strategies, CI/CD patterns
references/testing-comprehensive.md
如需详细的测试模式与技术,请参考:
- - ansible-lint配置、集成测试策略、CI/CD模式
references/testing-comprehensive.md
Related Skills
相关技能
- ansible-fundamentals - Core Ansible patterns
- ansible-idempotency - Ensuring tasks are idempotent
- ansible-fundamentals - 核心Ansible模式
- ansible-idempotency - 确保任务的幂等性