mirror of
https://github.com/trailofbits/algo.git
synced 2026-08-17 21:25:50 +02:00
* fix: add explicit bool filters for Ansible 12 jinja2_native compatibility Ansible 12 enables jinja2_native by default, which means string values like "true"/"false" are no longer automatically coerced to booleans in when: conditions and Jinja2 if statements. Add | bool filters to all boolean variable references in tasks, templates, and handlers. Also reformats long single-line Jinja2 conditionals into multi-line for readability, fixes GCE default() calls for native mode, adds help command to the algo script, and updates test fixtures to register the bool filter. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: add j2lint for Jinja2 template linting Add j2lint (aristanetworks/j2lint) to catch syntax errors, spacing issues, and operator formatting in Jinja2 templates. Integrated into pre-commit hooks, lint.yml CI, and smart-tests.yml. Rules S3/S5/S6/S7/V1 are ignored — they enforce conventions incompatible with Ansible's config-file-embedded templates. Also fixes int+1 → int + 1 operator spacing in server.conf.j2. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve all ansible-lint warnings and enforce zero-tolerance policy Fix 18 jinja[spacing] errors across 12 files by moving Jinja2 block delimiters to prevent YAML >- folding from introducing trailing spaces. Fix 27 key-order[task] warnings across 17 files by reordering task keys to canonical order (name → when → tags → environment → become → block). Promote key-order[task] and yaml[line-length] from warn_list to hard errors by removing warn_list entirely from .ansible-lint. Add zero-tolerance warning policy to CLAUDE.md explaining why warnings are unacceptable in a security tool and documenting resolution order. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Tests
Running Tests
# Run all linters (same as CI)
ansible-lint . && yamllint . && ruff check . && shellcheck scripts/*.sh
# Run Python unit tests
pytest tests/unit/ -q
# Run E2E connectivity tests (requires deployed Algo on localhost)
sudo tests/e2e/test-vpn-connectivity.sh both
Directory Structure
tests/
├── unit/ # Python unit tests (pytest)
│ ├── test_basic_sanity.py
│ ├── test_config_validation.py
│ ├── test_template_rendering.py
│ └── ...
├── e2e/ # End-to-end connectivity tests
│ └── test-vpn-connectivity.sh
├── integration/ # Integration test helpers
│ └── mock_modules/
├── fixtures/ # Shared test data
│ └── test_variables.yml
└── conftest.py # Pytest configuration
Test Coverage
| Category | Tests | What's Verified |
|---|---|---|
| Sanity | test_basic_sanity.py |
Python version, config syntax, playbook validity |
| Config | test_config_validation.py |
WireGuard/IPsec config formats, key validation |
| Templates | test_template_rendering.py |
Jinja2 template syntax, filter compatibility |
| Certificates | test_certificate_validation.py |
OpenSSL compatibility, PKCS#12 export |
| Cloud Providers | test_cloud_provider_configs.py |
Region formats, instance types, OS images |
| E2E | test-vpn-connectivity.sh |
WireGuard handshake, IPsec connection, DNS through VPN |
CI Workflows
| Workflow | Trigger | What It Does |
|---|---|---|
lint.yml |
All PRs | ansible-lint, yamllint, ruff, shellcheck |
main.yml |
Push to master | Syntax check, unit tests, Docker build |
integration-tests.yml |
PRs to roles/ | Full localhost deployment + E2E tests |
smart-tests.yml |
All PRs | Runs subset based on changed files |
Writing Tests
Python Unit Tests
Place in tests/unit/. Use fixtures from conftest.py:
def test_something(mock_ansible_module, jinja_env):
# mock_ansible_module - mocked AnsibleModule
# jinja_env - Jinja2 environment with Ansible filters
pass
Shell Scripts
Use bash strict mode and pass shellcheck:
#!/bin/bash
set -euo pipefail
Troubleshooting
E2E tests fail with "namespace already exists"
sudo ip netns del algo-client
Template tests fail with "filter not found"
Add the filter to the mock in conftest.py.
CI fails but local passes Check Python/Ansible versions match CI (Python 3.11, Ansible 12+).