# Check Mode (Dry Run)

Check mode allows you to preview changes before applying them, similar to a dry run.

## Overview

**Purpose:** See what Ansible would change without actually changing anything

**Command:**

```bash
auberge deploy --check
```

**Output:** Shows tasks that would execute and whether they would make changes

## Usage

### Deploy Check Mode (Primary)

```bash
# Interactive: select app(s) and host, then dry-run
auberge deploy --check

# Check a specific app
auberge deploy paperless --check

# Check all apps on a specific host
auberge deploy --all --host auberge --check
```

### Power-User: ansible run --check

For lower-level control (specific playbooks, skip-tags, etc.):

```bash
auberge ansible run --host auberge --playbook playbooks/apps.yml --check

# With skip-tags
auberge ansible run --host auberge --playbook playbooks/apps.yml --check --skip-tags navidrome

# With explicit tags
auberge ansible run --host auberge --check --tags baikal
```

## Understanding Output

### Status Indicators

Check mode uses the same status indicators as normal mode:

**ok (green):**

```
TASK [caddy : Check Caddy binary exists] ****
ok: [auberge]
```

- Task would run
- No changes would be made
- System already in desired state

**changed (yellow):**

```
TASK [baikal : Deploy Baikal config] ****
changed: [auberge]
```

- Task would make changes
- File/service/package would be modified
- **This is what you're looking for** in check mode

**skipped (cyan):**

```
TASK [bootstrap : Create ansible user] ****
skipping: [auberge]
```

- Task would be skipped
- Conditional not met (e.g., user already exists)

**failed (red):**

```
TASK [fail2ban : Start fail2ban service] ****
failed: [auberge]
```

- Task would fail
- Usually due to missing dependencies
- May be false positive in check mode (see limitations)

### Example Output

```
TASK [baikal : Install Baikal] ****
ok: [auberge]

TASK [baikal : Deploy configuration] ****
changed: [auberge]

TASK [baikal : Create data directory] ****
ok: [auberge]

TASK [baikal : Deploy systemd service] ****
changed: [auberge]

TASK [baikal : Start Baikal service] ****
changed: [auberge]

PLAY RECAP ****
auberge  : ok=15  changed=3  unreachable=0  failed=0  skipped=2
```

**Interpretation:**

- 3 tasks would make changes
- 15 tasks would run without changes
- 2 tasks would be skipped
- 0 failures

## What Check Mode Shows

### Files Changes

Shows whether files would be:

- Created
- Modified
- Deleted

**Example:**

```
TASK [caddy : Deploy Caddyfile] ****
changed: [auberge]
```

**Meaning:** Caddyfile content differs from template → would be updated

### Package Changes

Shows whether packages would be:

- Installed
- Updated
- Removed

**Example:**

```
TASK [apt : Install essential packages] ****
ok: [auberge]
```

**Meaning:** All packages already installed at correct version

### Service Changes

Shows whether services would be:

- Started
- Stopped
- Restarted
- Enabled/disabled

**Example:**

```
TASK [baikal : Restart Baikal] ****
changed: [auberge]
```

**Meaning:** Service would be restarted (likely due to config change)

### User/Group Changes

Shows whether users/groups would be:

- Created
- Modified
- Removed

**Example:**

```
TASK [ansible_user : Create ansible user] ****
ok: [auberge]
```

**Meaning:** User already exists with correct settings

## Limitations

Check mode has some limitations due to its non-destructive nature:

### 1. Dependency Failures

Tasks that depend on previous tasks may fail:

**Scenario:**

```yaml
- name: Create directory
  ansible.builtin.file:
    path: /app/data
    state: directory

- name: Copy file to directory
  ansible.builtin.copy:
    src: config.yml
    dest: /app/data/config.yml
```

**Check mode:** First task shows "changed", but directory isn't actually created. Second task may fail because directory doesn't exist.

**Workaround:** Ignore these failures - they wouldn't occur in real execution.

### 2. Conditional Logic

Some tasks check system state and conditionally execute:

```yaml
- name: Reload service
  ansible.builtin.systemd:
    name: baikal
    state: reloaded
  when: config_changed
```

**Check mode:** Condition might evaluate incorrectly if dependent task didn't actually run.

### 3. Command Modules

`ansible.builtin.command` and `ansible.builtin.shell` show "changed" even if they wouldn't change anything:

```yaml
- name: Get system info
  ansible.builtin.command: uname -a
  register: uname_output
```

**Check mode:** Always shows "changed" (because it doesn't actually run the command to check).

**Workaround:** Use `check_mode: no` for read-only commands:

```yaml
- name: Get system info
  ansible.builtin.command: uname -a
  register: uname_output
  check_mode: no # Always run, even in check mode
```

### 4. Handlers

Handlers are triggered but not executed:

```yaml
tasks:
  - name: Deploy config
    ansible.builtin.template:
      src: config.j2
      dest: /etc/app/config.yml
    notify: Restart app

handlers:
  - name: Restart app
    ansible.builtin.systemd:
      name: app
      state: restarted
```

**Check mode:**

- Task shows "changed"
- Handler is notified
- Handler doesn't actually restart service

**Output:**

```
RUNNING HANDLER [Restart app] ****
changed: [auberge]
```

**Meaning:** Handler would run, but service isn't actually restarted in check mode.

## Use Cases

### Before Deployment

Preview changes before deploying:

```bash
# Check what would change
auberge deploy paperless --check --host auberge

# If output looks good, deploy
auberge deploy paperless --host auberge
```

### After Config Changes

Verify your changes would apply correctly:

```bash
# Edit configuration
vim ansible/roles/baikal/templates/config.j2

# Check what would change
auberge deploy baikal --check --host auberge

# Review output, then apply
auberge deploy baikal --host auberge
```

### Testing New Playbooks

Test playbooks before first execution:

```bash
# Check new playbook (power-user)
auberge ansible run --host staging --playbook playbooks/new-feature.yml --check

# Review output for errors or unexpected changes
# Fix issues, re-check
# Deploy when ready
```

### Auditing Infrastructure

See what's out of sync with desired state:

```bash
auberge deploy --all --check --host auberge
```

**If many "changed" tasks:** System has drifted from configuration

**If few "changed" tasks:** System is consistent with playbooks

## Combining with Verbosity

For verbose output, use `ansible run` directly:

```bash
auberge ansible run --host auberge --check --tags baikal -vv
```

**Example output with `-v`:**

```
TASK [baikal : Deploy config] ****
changed: [auberge]
--- before: /etc/baikal/config
+++ after: /tmp/ansible-tmp-*/config.j2
@@ -1,3 +1,3 @@
 [server]
-hosts = 127.0.0.1:5232
+hosts = 0.0.0.0:5232
```

Shows **diff** of what would change.

## Diff Mode

Show file differences for all tasks (power-user):

```bash
auberge ansible run --host auberge --playbook playbooks/apps.yml --check --diff
```

**Output:**

```
TASK [caddy : Deploy Caddyfile] ****
--- before: /etc/caddy/Caddyfile
+++ after: /tmp/ansible-tmp-1234/Caddyfile.j2
@@ -10,6 +10,10 @@
 rss.example.com {
     reverse_proxy localhost:8000
 }
+
+music.example.com {
+    reverse_proxy localhost:4533
+}
```

**Benefit:** See exact changes before applying.

## Real Execution After Check

Check mode and normal mode are independent:

```bash
# Check mode does NOT affect system
auberge deploy paperless --check --host auberge

# Normal mode still needed to apply changes
auberge deploy paperless --host auberge
```

Check mode is **read-only** - it never modifies the system.

## Best Practices

### Always Check Before Major Changes

```bash
# Before full stack deployment
auberge deploy --all --check --host auberge

# Review output carefully
# Then deploy
auberge deploy --all --host auberge
```

### Combine with Backup

For production systems:

```bash
# 1. Create backup
auberge backup create --host production

# 2. Check what would change
auberge deploy --all --check --host production

# 3. If safe, apply
auberge deploy --all --host production

# 4. Verify, or restore if needed
```

### Use App Targeting for Focused Checks

```bash
# Check only what you're changing
auberge deploy baikal --check --host auberge
```

### Ignore Expected Failures

Some failures in check mode are normal:

- Missing directories that would be created
- Services that would be installed
- Dependencies not yet deployed

**Focus on:** Tasks that should already exist but show "changed" or "failed" unexpectedly.

## Related Pages

- [Running Playbooks](deployment/running-playbooks.md) - Actual execution
- [Tags](deployment/tags.md) - Selective execution
- [Playbooks](core-concepts/playbooks.md) - Playbook structure
