Skip to content

Commit e71f865

Browse files
Copilotjosecelano
andcommitted
docs: [#106] update documentation for centralized variables pattern
Co-authored-by: josecelano <[email protected]>
1 parent 18a0514 commit e71f865

File tree

3 files changed

+136
-5
lines changed

3 files changed

+136
-5
lines changed

docs/contributing/templates.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,72 @@ When adding a static Ansible playbook:
274274
- [ ] Create application step to execute the playbook
275275
- [ ] Verify playbook appears in `build/` directory during execution
276276

277+
## 🎯 Using Centralized Variables in Ansible Playbooks
278+
279+
When creating new Ansible playbooks that need dynamic variables (ports, paths, etc.), use the **centralized variables pattern** instead of creating new Tera templates.
280+
281+
### DO ✅
282+
283+
**Add variables to `templates/ansible/variables.yml.tera`:**
284+
285+
```yaml
286+
# System Configuration
287+
ssh_port: {{ ssh_port }}
288+
my_service_port: {{ my_service_port }} # ← Add your new variable
289+
```
290+
291+
**Reference variables in static playbook using `vars_files`:**
292+
293+
```yaml
294+
# templates/ansible/my-new-service.yml (static playbook, no .tera extension)
295+
---
296+
- name: Configure My Service
297+
hosts: all
298+
vars_files:
299+
- variables.yml # Load centralized variables
300+
301+
tasks:
302+
- name: Configure service port
303+
ansible.builtin.lineinfile:
304+
path: /etc/myservice/config
305+
line: "port={{ my_service_port }}"
306+
```
307+
308+
**Register playbook in `copy_static_templates()` method:**
309+
310+
```rust
311+
for playbook in &[
312+
"update-apt-cache.yml",
313+
"install-docker.yml",
314+
"my-new-service.yml", // ← Add here
315+
] {
316+
// ...
317+
}
318+
```
319+
320+
### DON'T ❌
321+
322+
- ❌ Create a new `.tera` template for the playbook
323+
- ❌ Create a new renderer/wrapper/context for each playbook
324+
- ❌ Add variables directly in `inventory.yml.tera` (unless inventory-specific)
325+
326+
### Benefits
327+
328+
1. **Minimal Code**: No Rust boilerplate (renderer, wrapper, context) needed
329+
2. **Centralized Management**: All variables in one place
330+
3. **Runtime Resolution**: Variables resolved by Ansible, not at template rendering
331+
4. **Easy Maintenance**: Adding new variables requires minimal changes
332+
333+
### When to Create a New Tera Template
334+
335+
Only create a new `.tera` template if:
336+
337+
1. The file **cannot** use Ansible's `vars_files` directive (e.g., inventory files)
338+
2. The file requires **complex logic** that Tera provides but Ansible doesn't
339+
3. The file needs **different variable scopes** than what centralized variables provide
340+
341+
Otherwise, use the centralized variables pattern for simplicity.
342+
277343
### Related Documentation
278344

279345
- **Architecture**: [`docs/technical/template-system-architecture.md`](../technical/template-system-architecture.md) - Understanding the two-phase template system

docs/technical/template-system-architecture.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,50 @@ The system operates through two levels of indirection to balance portability wit
5252
- **Use Case**: Configuration files requiring runtime parameters (IPs, usernames, paths)
5353
- **Registration**: Automatically discovered by `.tera` extension
5454

55+
## 🎨 Ansible Variables Pattern
56+
57+
For Ansible templates, the system uses a **hybrid approach** combining static playbooks with centralized variables:
58+
59+
### Tera Templates (2 templates)
60+
61+
1. `inventory.yml.tera` - Inventory requires direct variable substitution (Ansible inventories don't support vars_files)
62+
2. `variables.yml.tera` - Centralized variables for all playbooks
63+
64+
### Static Playbooks
65+
66+
- All playbooks are static YAML files (no `.tera` extension)
67+
- Playbooks reference variables via `vars_files: [variables.yml]`
68+
- Variables are resolved at Ansible runtime, not at template rendering time
69+
70+
### Benefits
71+
72+
- **Reduced Rust Boilerplate**: No per-playbook renderer/wrapper/context needed
73+
- **Centralized Variable Management**: All playbook variables in one place
74+
- **Consistency**: Follows the same pattern as OpenTofu's `variables.tfvars.tera`
75+
- **Maintainability**: Adding new playbooks requires minimal code changes
76+
77+
### Example
78+
79+
```yaml
80+
# templates/ansible/configure-firewall.yml (static playbook)
81+
---
82+
- name: Configure UFW firewall
83+
hosts: all
84+
vars_files:
85+
- variables.yml # Load centralized variables
86+
87+
tasks:
88+
- name: Allow SSH access
89+
community.general.ufw:
90+
port: "{{ ssh_port }}" # Variable from variables.yml
91+
```
92+
93+
```yaml
94+
# templates/ansible/variables.yml.tera (rendered once)
95+
---
96+
ssh_port: {{ ssh_port }}
97+
```
98+
5599
## 🔧 Key Components
56100
57101
### Template Manager

templates/ansible/README.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,22 @@ This directory contains Ansible playbook templates for the Torrust Tracker Deplo
2828

2929
- Sets up unattended-upgrades for automatic security patches
3030

31-
- **`configure-firewall.yml.tera`** - Configures UFW (Uncomplicated Firewall) with SSH lockout prevention
31+
- **`configure-firewall.yml`** - Configures UFW (Uncomplicated Firewall) with SSH lockout prevention
3232

3333
- ⚠️ **Critical**: This playbook configures restrictive firewall rules
3434
- Automatically preserves SSH access on the configured port to prevent lockout
35+
- Uses centralized variables from `variables.yml` (loaded via `vars_files`)
3536
- **Container Limitation**: Requires kernel capabilities (CAP_NET_ADMIN, CAP_NET_RAW) not available in unprivileged containers
3637
- **Automatic Skip**: Container-based E2E tests automatically skip this step via `TORRUST_TD_SKIP_FIREWALL_IN_CONTAINER` environment variable
3738
- Accepted values: `"true"` or `"false"` (case-sensitive, lowercase only)
3839
- Example: `TORRUST_TD_SKIP_FIREWALL_IN_CONTAINER=true`
39-
- **VM-only**: This playbook is only executed in VM-based deployments and tests### Configuration Files
40+
- **VM-only**: This playbook is only executed in VM-based deployments and tests
4041

41-
- **`ansible.cfg`** - Ansible configuration
42+
### Configuration Files
43+
44+
- **`ansible.cfg`** - Ansible configuration (static)
4245
- **`inventory.yml.tera`** - Inventory template file (processed by Tera templating engine)
46+
- **`variables.yml.tera`** - Centralized variables template (processed by Tera templating engine)
4347

4448
## Usage Order
4549

@@ -50,7 +54,7 @@ For a typical deployment:
5054
3. **`install-docker.yml`** - Install Docker
5155
4. **`install-docker-compose.yml`** - Install Docker Compose (optional)
5256
5. **`configure-security-updates.yml`** - Configure automatic security updates
53-
6. **`configure-firewall.yml.tera`** - Configure UFW firewall (VM-only, skipped in containers)
57+
6. **`configure-firewall.yml`** - Configure UFW firewall (VM-only, skipped in containers)
5458

5559
## CI/Testing Considerations
5660

@@ -63,6 +67,23 @@ For a typical deployment:
6367
- The deployer sets `TORRUST_TD_SKIP_FIREWALL_IN_CONTAINER=true` for container tests (accepts `"true"` or `"false"` only)
6468
- VM-based tests (LXD) have full kernel access and run the firewall playbook normally
6569

70+
## Variables Pattern
71+
72+
This directory uses a **centralized variables pattern**:
73+
74+
- **`variables.yml.tera`** - Centralized variables (rendered at runtime with Tera)
75+
- **`inventory.yml.tera`** - Connection variables (rendered at runtime with Tera)
76+
- **`*.yml`** - Static playbooks that load `variables.yml` via `vars_files` directive
77+
78+
### When Adding New Playbooks
79+
80+
1. **Add variables** to `variables.yml.tera`
81+
2. **Create static** `.yml` playbook (not `.tera`)
82+
3. **Add `vars_files: [variables.yml]`** to playbook
83+
4. **Register** in `copy_static_templates()` if new static playbook
84+
85+
This pattern reduces Rust boilerplate (no per-playbook renderer/wrapper/context needed) while providing centralized variable management.
86+
6687
## Template Processing
6788

68-
These files are processed by the Tera templating engine and written to the `build/ansible/` directory during the build process.
89+
Files with `.tera` extension are processed by the Tera templating engine. All files are written to the `build/ansible/` directory during the build process.

0 commit comments

Comments
 (0)