mirror of
https://github.com/trailofbits/algo.git
synced 2026-08-17 21:25:50 +02:00
Phase 1: Quick wins for code quality and test infrastructure (#14907)
- Replace ignore_errors: true with failed_when: false in 5 files (main.yml, users.yml, ubuntu.yml, umount.yml, test-wireguard-real-async.yml) - Add pytest.ini configuration for test discovery - Add tests/conftest.py with shared fixtures and mock helpers The failed_when: false pattern is preferred by ansible-lint as it explicitly indicates expected failure handling rather than silently ignoring all errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -18,7 +18,7 @@
|
||||
- name: Ensure the requirements installed
|
||||
debug:
|
||||
msg: "{{ '192.168.1.1' | ansible.utils.ipaddr }}"
|
||||
ignore_errors: true
|
||||
failed_when: false
|
||||
no_log: true
|
||||
register: ipaddr
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
- block:
|
||||
- name: MacOS | check fs the ramdisk exists
|
||||
command: /usr/sbin/diskutil info "{{ facts.tmpfs_volume_name }}"
|
||||
ignore_errors: true
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
register: diskutil_info
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
[pytest]
|
||||
testpaths = tests/unit
|
||||
python_files = test_*.py
|
||||
python_classes = Test*
|
||||
python_functions = test_*
|
||||
addopts = -v --tb=short
|
||||
filterwarnings =
|
||||
ignore::DeprecationWarning
|
||||
ignore::PendingDeprecationWarning
|
||||
@@ -105,7 +105,7 @@
|
||||
|
||||
- name: Check apparmor support
|
||||
command: apparmor_status
|
||||
ignore_errors: true
|
||||
failed_when: false
|
||||
changed_when: false
|
||||
register: apparmor_status
|
||||
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
"""Shared pytest fixtures for Algo VPN tests."""
|
||||
|
||||
import base64
|
||||
import secrets
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
# Add library directory to path for custom module imports
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent / "library"))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_variables():
|
||||
"""Load test variables from YAML fixture."""
|
||||
fixture_path = Path(__file__).parent / "fixtures" / "test_variables.yml"
|
||||
with open(fixture_path) as f:
|
||||
return yaml.safe_load(f)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def test_config(test_variables):
|
||||
"""Get test configuration with common defaults."""
|
||||
return test_variables.copy()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def temp_directory():
|
||||
"""Create a temporary directory for test files."""
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
yield Path(tmpdir)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wireguard_private_key():
|
||||
"""Generate a random WireGuard-compatible private key."""
|
||||
raw_key = secrets.token_bytes(32)
|
||||
return base64.b64encode(raw_key).decode()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def wireguard_key_pair(temp_directory):
|
||||
"""Generate a WireGuard key pair and return paths and values."""
|
||||
raw_key = secrets.token_bytes(32)
|
||||
b64_key = base64.b64encode(raw_key).decode()
|
||||
|
||||
private_key_path = temp_directory / "private.key"
|
||||
private_key_path.write_bytes(raw_key)
|
||||
|
||||
return {
|
||||
"private_key_raw": raw_key,
|
||||
"private_key_b64": b64_key,
|
||||
"private_key_path": str(private_key_path),
|
||||
}
|
||||
|
||||
|
||||
class MockAnsibleModule:
|
||||
"""Mock AnsibleModule for testing custom Ansible modules."""
|
||||
|
||||
def __init__(self, params):
|
||||
"""Initialize with module parameters."""
|
||||
self.params = params
|
||||
self.result = {}
|
||||
self.failed = False
|
||||
self.fail_msg = None
|
||||
|
||||
def fail_json(self, **kwargs):
|
||||
"""Record failure and raise exception."""
|
||||
self.failed = True
|
||||
self.fail_msg = kwargs.get("msg", "Unknown error")
|
||||
raise Exception(f"Module failed: {self.fail_msg}")
|
||||
|
||||
def exit_json(self, **kwargs):
|
||||
"""Record successful result."""
|
||||
self.result = kwargs
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_ansible_module():
|
||||
"""Fixture providing MockAnsibleModule class."""
|
||||
return MockAnsibleModule
|
||||
|
||||
|
||||
# Jinja2 mock filters for template testing
|
||||
def mock_to_uuid(value):
|
||||
"""Mock the to_uuid filter."""
|
||||
return "12345678-1234-5678-1234-567812345678"
|
||||
|
||||
|
||||
def mock_bool(value):
|
||||
"""Mock the bool filter."""
|
||||
return str(value).lower() in ("true", "1", "yes", "on")
|
||||
|
||||
|
||||
def mock_lookup(lookup_type, path):
|
||||
"""Mock the lookup function."""
|
||||
if lookup_type == "file":
|
||||
if "private" in path:
|
||||
return "MOCK_PRIVATE_KEY_BASE64=="
|
||||
elif "public" in path:
|
||||
return "MOCK_PUBLIC_KEY_BASE64=="
|
||||
elif "preshared" in path:
|
||||
return "MOCK_PRESHARED_KEY_BASE64=="
|
||||
return "MOCK_LOOKUP_DATA"
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def jinja2_env():
|
||||
"""Create a Jinja2 environment with mock Ansible filters."""
|
||||
from jinja2 import Environment, FileSystemLoader, StrictUndefined
|
||||
|
||||
def create_env(template_dir):
|
||||
env = Environment(loader=FileSystemLoader(template_dir), undefined=StrictUndefined)
|
||||
env.globals["lookup"] = mock_lookup
|
||||
env.filters["to_uuid"] = mock_to_uuid
|
||||
env.filters["bool"] = mock_bool
|
||||
return env
|
||||
|
||||
return create_env
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project_root():
|
||||
"""Return the project root directory."""
|
||||
return Path(__file__).parent.parent
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def roles_dir(project_root):
|
||||
"""Return the roles directory."""
|
||||
return project_root / "roles"
|
||||
|
||||
|
||||
# Skip markers for conditional tests
|
||||
def pytest_configure(config):
|
||||
"""Register custom markers."""
|
||||
config.addinivalue_line("markers", "requires_wireguard: mark test as requiring WireGuard tools")
|
||||
config.addinivalue_line("markers", "slow: mark test as slow running")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def skip_wireguard_tests(request):
|
||||
"""Skip tests marked with requires_wireguard if WireGuard tools aren't available."""
|
||||
if request.node.get_closest_marker("requires_wireguard"):
|
||||
import shutil
|
||||
|
||||
if not shutil.which("wg"):
|
||||
pytest.skip("WireGuard tools not available")
|
||||
@@ -55,7 +55,7 @@
|
||||
mode: "0600"
|
||||
when: item.changed
|
||||
loop: "{{ wg_genkey_results.results }}"
|
||||
ignore_errors: true
|
||||
failed_when: false
|
||||
|
||||
- name: Cleanup
|
||||
file:
|
||||
|
||||
Reference in New Issue
Block a user