Fix StrongSwan CRL reread handler race condition

The ipsec rereadcrls command was failing with exit code 7 when the IPsec
daemon wasn't fully started yet. This is a timing issue that can occur
during initial setup.

Added retry logic to:
1. Wait up to 10 seconds for the IPsec daemon to be ready
2. Check daemon status before attempting CRL operations
3. Gracefully handle the case where daemon isn't ready

Also fixed Python linting issues (whitespace) in test files caught by ruff.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Dan Guido 2025-08-06 21:22:11 -07:00
parent 808fd85956
commit 4be204f1d5
3 changed files with 108 additions and 101 deletions

View file

@ -9,4 +9,14 @@
service: name=apparmor state=restarted service: name=apparmor state=restarted
- name: rereadcrls - name: rereadcrls
shell: ipsec rereadcrls; ipsec purgecrls shell: |
# Wait for ipsec daemon to be ready (up to 10 seconds)
for i in $(seq 1 10); do
if ipsec statusall >/dev/null 2>&1; then
ipsec rereadcrls && ipsec purgecrls
exit 0
fi
sleep 1
done
# If daemon still not ready, try anyway but don't fail the playbook
ipsec rereadcrls; ipsec purgecrls || true

View file

@ -6,7 +6,6 @@ Tests all strongswan role templates with various configurations.
import os import os
import sys import sys
import uuid import uuid
from pathlib import Path
from jinja2 import Environment, FileSystemLoader, StrictUndefined from jinja2 import Environment, FileSystemLoader, StrictUndefined
@ -189,7 +188,7 @@ def test_openssl_template_constraints():
return True return True
try: try:
with open(openssl_path, 'r') as f: with open(openssl_path) as f:
content = yaml.safe_load(f) content = yaml.safe_load(f)
# Find the CA CSR task # Find the CA CSR task

View file

@ -7,16 +7,14 @@ This script checks for:
3. Common anti-patterns 3. Common anti-patterns
""" """
import os
import re import re
import sys import sys
from pathlib import Path from pathlib import Path
from typing import List, Tuple
from jinja2 import Environment, FileSystemLoader, StrictUndefined, TemplateSyntaxError, meta from jinja2 import Environment, FileSystemLoader, StrictUndefined, TemplateSyntaxError, meta
def find_jinja2_templates(root_dir: str = '.') -> List[Path]: def find_jinja2_templates(root_dir: str = '.') -> list[Path]:
"""Find all Jinja2 template files in the project.""" """Find all Jinja2 template files in the project."""
templates = [] templates = []
patterns = ['**/*.j2', '**/*.jinja2', '**/*.yml.j2', '**/*.conf.j2'] patterns = ['**/*.j2', '**/*.jinja2', '**/*.yml.j2', '**/*.conf.j2']
@ -33,7 +31,7 @@ def find_jinja2_templates(root_dir: str = '.') -> List[Path]:
return sorted(templates) return sorted(templates)
def check_inline_comments_in_expressions(template_content: str, template_path: Path) -> List[str]: def check_inline_comments_in_expressions(template_content: str, template_path: Path) -> list[str]:
""" """
Check for inline comments (#) within Jinja2 expressions. Check for inline comments (#) within Jinja2 expressions.
This is the error we just fixed in openssl.yml. This is the error we just fixed in openssl.yml.
@ -68,7 +66,7 @@ def check_inline_comments_in_expressions(template_content: str, template_path: P
return errors return errors
def check_undefined_variables(template_path: Path) -> List[str]: def check_undefined_variables(template_path: Path) -> list[str]:
""" """
Parse template and extract all undefined variables. Parse template and extract all undefined variables.
This helps identify what variables need to be provided. This helps identify what variables need to be provided.
@ -76,7 +74,7 @@ def check_undefined_variables(template_path: Path) -> List[str]:
errors = [] errors = []
try: try:
with open(template_path, 'r') as f: with open(template_path) as f:
template_content = f.read() template_content = f.read()
env = Environment(undefined=StrictUndefined) env = Environment(undefined=StrictUndefined)
@ -101,14 +99,14 @@ def check_undefined_variables(template_path: Path) -> List[str]:
f"{template_path}: Uses undefined variables: {', '.join(sorted(unknown_vars))}" f"{template_path}: Uses undefined variables: {', '.join(sorted(unknown_vars))}"
) )
except Exception as e: except Exception:
# Don't report parse errors here, they're handled elsewhere # Don't report parse errors here, they're handled elsewhere
pass pass
return errors return errors
def validate_template_syntax(template_path: Path) -> Tuple[bool, List[str]]: def validate_template_syntax(template_path: Path) -> tuple[bool, list[str]]:
""" """
Validate a single template for syntax errors. Validate a single template for syntax errors.
Returns (is_valid, list_of_errors) Returns (is_valid, list_of_errors)
@ -126,7 +124,7 @@ def validate_template_syntax(template_path: Path) -> Tuple[bool, List[str]]:
if template_path.name in ansible_specific_templates: if template_path.name in ansible_specific_templates:
# Still check for inline comments but skip full parsing # Still check for inline comments but skip full parsing
try: try:
with open(template_path, 'r') as f: with open(template_path) as f:
template_content = f.read() template_content = f.read()
errors.extend(check_inline_comments_in_expressions(template_content, template_path)) errors.extend(check_inline_comments_in_expressions(template_content, template_path))
except Exception: except Exception:
@ -134,7 +132,7 @@ def validate_template_syntax(template_path: Path) -> Tuple[bool, List[str]]:
return len(errors) == 0, errors return len(errors) == 0, errors
try: try:
with open(template_path, 'r') as f: with open(template_path) as f:
template_content = f.read() template_content = f.read()
# Check for inline comments first (our custom check) # Check for inline comments first (our custom check)
@ -171,12 +169,12 @@ def validate_template_syntax(template_path: Path) -> Tuple[bool, List[str]]:
return len(errors) == 0, errors return len(errors) == 0, errors
def check_common_antipatterns(template_path: Path) -> List[str]: def check_common_antipatterns(template_path: Path) -> list[str]:
"""Check for common Jinja2 anti-patterns.""" """Check for common Jinja2 anti-patterns."""
warnings = [] warnings = []
try: try:
with open(template_path, 'r') as f: with open(template_path) as f:
content = f.read() content = f.read()
# Check for missing spaces around filters # Check for missing spaces around filters