Refactor test utilities and enhance ASGI settings

- Cleaned up and standardized assertions in ApiTestMixin for API response validation.
- Updated ASGI settings to use os.environ for setting the DJANGO_SETTINGS_MODULE.
- Removed unused imports and improved formatting in settings.py.
- Refactored URL patterns in urls.py for better readability and organization.
- Enhanced view functions in views.py for consistency and clarity.
- Added .flake8 configuration for linting and style enforcement.
- Introduced type stubs for django-environ to improve type checking with Pylance.
This commit is contained in:
pacnpal
2025-08-20 19:51:59 -04:00
parent 69c07d1381
commit 66ed4347a9
230 changed files with 15094 additions and 11578 deletions

View File

@@ -5,7 +5,6 @@ This script provides basic validation to check if our autoinstall config
complies with the official schema structure.
"""
import json
import yaml
import sys
from pathlib import Path
@@ -13,15 +12,15 @@ from pathlib import Path
def load_autoinstall_config(template_path: str) -> dict:
"""Load the autoinstall configuration from the template file."""
with open(template_path, 'r') as f:
with open(template_path, "r") as f:
content = f.read()
# Parse the cloud-config YAML
config = yaml.safe_load(content)
# Extract the autoinstall section
if 'autoinstall' in config:
return config['autoinstall']
if "autoinstall" in config:
return config["autoinstall"]
else:
raise ValueError("No autoinstall section found in cloud-config")
@@ -29,154 +28,158 @@ def load_autoinstall_config(template_path: str) -> dict:
def validate_required_fields(config: dict) -> list:
"""Validate required fields according to schema."""
errors = []
# Check version field (required)
if 'version' not in config:
if "version" not in config:
errors.append("Missing required field: version")
elif not isinstance(config['version'], int) or config['version'] != 1:
elif not isinstance(config["version"], int) or config["version"] != 1:
errors.append("Invalid version: must be integer 1")
return errors
def validate_identity_section(config: dict) -> list:
"""Validate identity section."""
errors = []
if 'identity' in config:
identity = config['identity']
required_fields = ['username', 'hostname', 'password']
if "identity" in config:
identity = config["identity"]
required_fields = ["username", "hostname", "password"]
for field in required_fields:
if field not in identity:
errors.append(f"Identity section missing required field: {field}")
# Additional validation
if 'username' in identity and not isinstance(identity['username'], str):
if "username" in identity and not isinstance(identity["username"], str):
errors.append("Identity username must be a string")
if 'hostname' in identity and not isinstance(identity['hostname'], str):
if "hostname" in identity and not isinstance(identity["hostname"], str):
errors.append("Identity hostname must be a string")
return errors
def validate_network_section(config: dict) -> list:
"""Validate network section."""
errors = []
if 'network' in config:
network = config['network']
if 'version' not in network:
if "network" in config:
network = config["network"]
if "version" not in network:
errors.append("Network section missing required field: version")
elif network['version'] != 2:
elif network["version"] != 2:
errors.append("Network version must be 2")
return errors
def validate_keyboard_section(config: dict) -> list:
"""Validate keyboard section."""
errors = []
if 'keyboard' in config:
keyboard = config['keyboard']
if 'layout' not in keyboard:
if "keyboard" in config:
keyboard = config["keyboard"]
if "layout" not in keyboard:
errors.append("Keyboard section missing required field: layout")
return errors
def validate_ssh_section(config: dict) -> list:
"""Validate SSH section."""
errors = []
if 'ssh' in config:
ssh = config['ssh']
if 'install-server' in ssh and not isinstance(ssh['install-server'], bool):
if "ssh" in config:
ssh = config["ssh"]
if "install-server" in ssh and not isinstance(ssh["install-server"], bool):
errors.append("SSH install-server must be boolean")
if 'authorized-keys' in ssh and not isinstance(ssh['authorized-keys'], list):
if "authorized-keys" in ssh and not isinstance(ssh["authorized-keys"], list):
errors.append("SSH authorized-keys must be an array")
if 'allow-pw' in ssh and not isinstance(ssh['allow-pw'], bool):
if "allow-pw" in ssh and not isinstance(ssh["allow-pw"], bool):
errors.append("SSH allow-pw must be boolean")
return errors
def validate_packages_section(config: dict) -> list:
"""Validate packages section."""
errors = []
if 'packages' in config:
packages = config['packages']
if "packages" in config:
packages = config["packages"]
if not isinstance(packages, list):
errors.append("Packages must be an array")
else:
for i, package in enumerate(packages):
if not isinstance(package, str):
errors.append(f"Package at index {i} must be a string")
return errors
def validate_commands_sections(config: dict) -> list:
"""Validate early-commands and late-commands sections."""
errors = []
for section_name in ['early-commands', 'late-commands']:
for section_name in ["early-commands", "late-commands"]:
if section_name in config:
commands = config[section_name]
if not isinstance(commands, list):
errors.append(f"{section_name} must be an array")
else:
for i, command in enumerate(commands):
if not isinstance(command, (str, list)):
errors.append(f"{section_name} item at index {i} must be string or array")
errors.append(
f"{section_name} item at index {i} must be string or array"
)
elif isinstance(command, list):
for j, cmd_part in enumerate(command):
if not isinstance(cmd_part, str):
errors.append(f"{section_name}[{i}][{j}] must be a string")
errors.append(
f"{section_name}[{i}][{j}] must be a string"
)
return errors
def validate_shutdown_section(config: dict) -> list:
"""Validate shutdown section."""
errors = []
if 'shutdown' in config:
shutdown = config['shutdown']
valid_values = ['reboot', 'poweroff']
if "shutdown" in config:
shutdown = config["shutdown"]
valid_values = ["reboot", "poweroff"]
if shutdown not in valid_values:
errors.append(f"Shutdown must be one of: {valid_values}")
return errors
def main():
"""Main validation function."""
template_path = Path(__file__).parent / "cloud-init-template.yaml"
if not template_path.exists():
print(f"Error: Template file not found at {template_path}")
sys.exit(1)
try:
# Load the autoinstall configuration
print(f"Loading autoinstall config from {template_path}")
config = load_autoinstall_config(str(template_path))
# Run validation checks
all_errors = []
all_errors.extend(validate_required_fields(config))
all_errors.extend(validate_identity_section(config))
all_errors.extend(validate_network_section(config))
@@ -185,7 +188,7 @@ def main():
all_errors.extend(validate_packages_section(config))
all_errors.extend(validate_commands_sections(config))
all_errors.extend(validate_shutdown_section(config))
# Report results
if all_errors:
print("\n❌ Validation failed with the following errors:")
@@ -195,11 +198,11 @@ def main():
else:
print("\n✅ Autoinstall configuration validation passed!")
print("Configuration appears to comply with Ubuntu autoinstall schema.")
# Print summary of detected sections
sections = list(config.keys())
print(f"\nDetected sections: {', '.join(sorted(sections))}")
except Exception as e:
print(f"Error during validation: {e}")
sys.exit(1)