ansible-testing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Ansible Testing

Ansible 测试

Testing strategies and ansible-lint configuration for Ansible automation.
Ansible自动化的测试策略与ansible-lint配置。

ansible-lint

ansible-lint

Running Lint

运行代码检查

bash
undefined
bash
undefined

Via 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/
undefined
uv run ansible-lint -v ansible/
undefined

Configuration File

配置文件

Located at
ansible/.ansible-lint
:
yaml
---
位于
ansible/.ansible-lint
:
yaml
---

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]
undefined
warn_list:
  • fqcn[action-core]
  • fqcn[action]
  • no-handler
  • name[play]
undefined

Common Rule Categories

常见规则类别

CategoryDescription
fqcn
Fully qualified collection names
yaml
YAML formatting (indentation, line length)
name
Task/play naming conventions
command-instead-of-module
Using command when module exists
no-changed-when
Missing changed_when on command
risky-file-permissions
Missing explicit file permissions
类别描述
fqcn
完整限定集合名称
yaml
YAML格式(缩进、行长度)
name
任务/剧本命名规范
command-instead-of-module
已有模块却使用command
no-changed-when
命令缺少changed_when
risky-file-permissions
缺少明确的文件权限

Fixing Common Issues

修复常见问题

Missing name on task:
yaml
undefined
任务缺少名称:
yaml
undefined

BAD

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

**短模块名称:**

```yaml

BAD (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:**

```yaml

BAD (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:**

```yaml

BAD (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
undefined

Syntax Checking

语法检查

Validate playbook syntax before running:
bash
undefined
运行前验证playbook语法:
bash
undefined

Check 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
undefined
uv run ansible-playbook playbooks/my-playbook.yml --check --diff
undefined

Idempotency Testing

幂等性测试

Verify playbooks are idempotent by running twice:
bash
undefined
通过运行两次验证playbook的幂等性:
bash
undefined

First 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

undefined
undefined

Automated 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
fi
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
fi

Integration Testing

集成测试

Test Against Real Infrastructure

针对真实基础设施测试

bash
undefined
bash
undefined

Limit 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
undefined
uv run ansible-playbook playbooks/deploy.yml --limit test_hosts -vv
undefined

Pre-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
undefined

playbooks/test-role.yml

playbooks/test-role.yml


  • name: Test role functionality hosts: test_hosts become: true
    vars: test_mode: true
    roles:
    • 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: true
    vars: test_mode: true
    roles:
    • 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

CI/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
undefined
bash
undefined

Increase 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
undefined
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
undefined

Debug 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 > 0
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 > 0

Step Mode

分步模式

bash
undefined
bash
undefined

Pause after each task

Pause after each task

uv run ansible-playbook playbook.yml --step
undefined
uv run ansible-playbook playbook.yml --step
undefined

Lint Profiles

代码检查级别

Choose appropriate profile based on needs:
ProfileStrictnessUse Case
min
LowestLegacy code, quick fixes
basic
LowDevelopment
moderate
MediumGeneral infrastructure
safety
HighSecurity-sensitive
production
HighestProduction deployments
根据需求选择合适的级别:
级别严格程度使用场景
min
最低遗留代码、快速修复
basic
开发环境
moderate
中等通用基础设施
safety
安全敏感场景
production
最高生产环境部署

Additional Resources

额外资源

For detailed testing patterns and techniques, consult:
  • references/testing-comprehensive.md
    - ansible-lint configuration, integration testing strategies, CI/CD patterns
如需详细的测试模式与技术,请参考:
  • references/testing-comprehensive.md
    - ansible-lint配置、集成测试策略、CI/CD模式

Related Skills

相关技能

  • ansible-fundamentals - Core Ansible patterns
  • ansible-idempotency - Ensuring tasks are idempotent
  • ansible-fundamentals - 核心Ansible模式
  • ansible-idempotency - 确保任务的幂等性