Files
thrillwiki_django_no_react/scripts/unraid/validate-autoinstall.py
pacnpal c26414ff74 Add comprehensive tests for Parks API and models
- Implemented extensive test cases for the Parks API, covering endpoints for listing, retrieving, creating, updating, and deleting parks.
- Added tests for filtering, searching, and ordering parks in the API.
- Created tests for error handling in the API, including malformed JSON and unsupported methods.
- Developed model tests for Park, ParkArea, Company, and ParkReview models, ensuring validation and constraints are enforced.
- Introduced utility mixins for API and model testing to streamline assertions and enhance test readability.
- Included integration tests to validate complete workflows involving park creation, retrieval, updating, and deletion.
2025-08-17 19:36:20 -04:00

210 lines
6.7 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Validate autoinstall configuration against Ubuntu's schema.
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
def load_autoinstall_config(template_path: str) -> dict:
"""Load the autoinstall configuration from the template file."""
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']
else:
raise ValueError("No autoinstall section found in cloud-config")
def validate_required_fields(config: dict) -> list:
"""Validate required fields according to schema."""
errors = []
# Check version field (required)
if 'version' not in config:
errors.append("Missing required field: version")
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']
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):
errors.append("Identity username must be a string")
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:
errors.append("Network section missing required field: version")
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:
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):
errors.append("SSH install-server must be boolean")
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):
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 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']:
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")
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")
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 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))
all_errors.extend(validate_keyboard_section(config))
all_errors.extend(validate_ssh_section(config))
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:")
for error in all_errors:
print(f" - {error}")
sys.exit(1)
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)
if __name__ == "__main__":
main()