debian-forge/debian-forge-tests/test-blueprint-system.py
robojerk 502e1469ae
Some checks failed
Checks / Spelling (push) Has been cancelled
Checks / Python Linters (push) Has been cancelled
Checks / Shell Linters (push) Has been cancelled
Checks / 📦 Packit config lint (push) Has been cancelled
Checks / 🔍 Check for valid snapshot urls (push) Has been cancelled
Checks / 🔍 Check JSON files for formatting consistency (push) Has been cancelled
Generate / Documentation (push) Has been cancelled
Generate / Test Data (push) Has been cancelled
Tests / Unittest (push) Has been cancelled
Tests / Assembler test (legacy) (push) Has been cancelled
Tests / Smoke run: unittest as normal user on default runner (push) Has been cancelled
Move composer scripts to root directory and add comprehensive Debian Atomic support
2025-08-23 08:02:45 -07:00

381 lines
12 KiB
Python

#!/usr/bin/env python3
"""
Test Debian Atomic Blueprint System
This script validates the blueprint system for Debian atomic images,
testing blueprint structure, validation, and OSBuild pipeline integration.
"""
import json
import os
import sys
import tempfile
from pathlib import Path
def test_blueprint_structure():
"""Test basic blueprint structure validation"""
print("Testing blueprint structure validation...")
# Test basic blueprint
basic_blueprint = {
"name": "debian-atomic-base",
"description": "Debian Atomic Base System",
"version": "0.0.1",
"packages": [
{"name": "systemd"},
{"name": "systemd-sysv"},
{"name": "dbus"},
{"name": "udev"},
{"name": "ostree"},
{"name": "linux-image-amd64"}
],
"modules": [],
"groups": [],
"customizations": {
"user": [
{
"name": "debian",
"description": "Debian user",
"password": "$6$rounds=656000$YQvKxqQKqQKqQKqQ$...",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...",
"home": "/home/debian",
"shell": "/bin/bash",
"groups": ["wheel"],
"uid": 1000,
"gid": 1000
}
],
"services": {
"enabled": ["sshd", "systemd-networkd"]
}
}
}
# Validate required fields
required_fields = ["name", "description", "version", "packages"]
for field in required_fields:
if field not in basic_blueprint:
print(f" ❌ Missing required field: {field}")
return False
# Validate packages structure
if not isinstance(basic_blueprint["packages"], list):
print(" ❌ Packages must be a list")
return False
for package in basic_blueprint["packages"]:
if "name" not in package:
print(" ❌ Package missing name")
return False
print(" ✅ Basic blueprint structure is valid")
return True
def test_blueprint_variants():
"""Test different blueprint variants"""
print("\nTesting blueprint variants...")
variants = [
"debian-atomic-base",
"debian-atomic-workstation",
"debian-atomic-server"
]
for variant in variants:
blueprint = create_variant_blueprint(variant)
# Validate variant-specific requirements
if variant == "debian-atomic-workstation":
if "desktop" not in [g["name"] for g in blueprint.get("groups", [])]:
print(f"{variant} missing desktop group")
return False
elif variant == "debian-atomic-server":
if "server" not in [g["name"] for g in blueprint.get("groups", [])]:
print(f"{variant} missing server group")
return False
print(f"{variant} blueprint is valid")
return True
def create_variant_blueprint(variant):
"""Create a blueprint for a specific variant"""
base_packages = ["systemd", "systemd-sysv", "dbus", "udev", "ostree", "linux-image-amd64"]
if variant == "debian-atomic-workstation":
packages = base_packages + ["gnome-shell", "gnome-session", "gdm3", "network-manager", "firefox-esr"]
groups = [{"name": "desktop"}]
services = ["sshd", "systemd-networkd", "gdm3", "NetworkManager"]
elif variant == "debian-atomic-server":
packages = base_packages + ["nginx", "postgresql", "redis-server", "fail2ban"]
groups = [{"name": "server"}]
services = ["sshd", "systemd-networkd", "nginx", "postgresql", "redis-server", "fail2ban"]
else: # base
packages = base_packages
groups = []
services = ["sshd", "systemd-networkd"]
return {
"name": variant,
"description": f"Debian Atomic {variant.replace('debian-atomic-', '').title()}",
"version": "0.0.1",
"packages": [{"name": pkg} for pkg in packages],
"modules": [],
"groups": groups,
"customizations": {
"user": [
{
"name": "debian",
"description": "Debian user",
"password": "$6$rounds=656000$YQvKxqQKqQKqQKqQ$...",
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC...",
"home": "/home/debian",
"shell": "/bin/bash",
"groups": ["wheel"] + [g["name"] for g in groups],
"uid": 1000,
"gid": 1000
}
],
"services": {
"enabled": services
}
}
}
def test_blueprint_variables():
"""Test blueprint variables and templating"""
print("\nTesting blueprint variables...")
variables = {
"architecture": "amd64",
"suite": "bookworm",
"variant": "minbase",
"mirror": "http://deb.debian.org/debian",
"apt_proxy": "http://192.168.1.101:3142"
}
# Validate variable types
expected_types = {
"architecture": str,
"suite": str,
"variant": str,
"mirror": str,
"apt_proxy": str
}
for var, expected_type in expected_types.items():
if var in variables and not isinstance(variables[var], expected_type):
print(f" ❌ Variable {var} has wrong type")
return False
# Test package groups
package_groups = {
"base": ["systemd", "systemd-sysv", "dbus", "udev", "ostree"],
"desktop": ["gnome-shell", "gnome-session", "gdm3"],
"server": ["nginx", "postgresql", "redis-server"],
"development": ["build-essential", "git", "python3", "nodejs"],
"security": ["fail2ban", "unattended-upgrades", "rkhunter"]
}
for group, packages in package_groups.items():
if not isinstance(packages, list):
print(f" ❌ Package group {group} must be a list")
return False
print(" ✅ Blueprint variables are valid")
return True
def test_osbuild_pipeline_integration():
"""Test OSBuild pipeline integration"""
print("\nTesting OSBuild pipeline integration...")
# Test debootstrap stage
debootstrap_stage = {
"type": "org.osbuild.debootstrap",
"options": {
"suite": "bookworm",
"mirror": "http://deb.debian.org/debian",
"arch": "amd64",
"variant": "minbase",
"apt_proxy": "http://192.168.1.101:3142"
}
}
if "type" not in debootstrap_stage:
print(" ❌ Stage missing type")
return False
if "options" not in debootstrap_stage:
print(" ❌ Stage missing options")
return False
# Test apt stage
apt_stage = {
"type": "org.osbuild.apt",
"options": {
"packages": ["systemd", "systemd-sysv", "dbus", "udev"],
"recommends": False,
"update": True,
"apt_proxy": "http://192.168.1.101:3142"
}
}
if "type" not in apt_stage:
print(" ❌ Stage missing type")
return False
# Test ostree commit stage
ostree_stage = {
"type": "org.osbuild.ostree.commit",
"options": {
"repo": "debian-atomic",
"branch": "debian/bookworm",
"subject": "Debian Bookworm atomic system",
"body": "Debian Bookworm minbase system with systemd and OSTree"
}
}
if "type" not in ostree_stage:
print(" ❌ Stage missing type")
return False
print(" ✅ OSBuild pipeline integration is valid")
return True
def test_blueprint_validation():
"""Test blueprint validation rules"""
print("\nTesting blueprint validation rules...")
# Test invalid blueprint (missing required fields)
invalid_blueprint = {
"name": "invalid-blueprint"
# Missing description, version, packages
}
required_fields = ["description", "version", "packages"]
missing_fields = []
for field in required_fields:
if field not in invalid_blueprint:
missing_fields.append(field)
if missing_fields:
print(f" ✅ Correctly identified missing fields: {missing_fields}")
else:
print(" ❌ Failed to identify missing fields")
return False
# Test package validation
invalid_package = {
"name": "debian-atomic-invalid",
"description": "Invalid blueprint",
"version": "0.0.1",
"packages": [
{"wrong_field": "systemd"} # Missing 'name' field
]
}
invalid_packages = []
for package in invalid_package["packages"]:
if "name" not in package:
invalid_packages.append(package)
if invalid_packages:
print(" ✅ Correctly identified invalid packages")
else:
print(" ❌ Failed to identify invalid packages")
return False
print(" ✅ Blueprint validation rules work correctly")
return True
def test_composer_integration():
"""Test composer integration patterns"""
print("\nTesting composer integration patterns...")
# Test composer API structure
composer_api = {
"endpoints": {
"blueprints": "/api/v1/blueprints",
"compose": "/api/v1/compose",
"status": "/api/v1/compose/status",
"logs": "/api/v1/compose/logs"
},
"methods": {
"submit_blueprint": "POST",
"get_blueprint": "GET",
"start_compose": "POST",
"get_compose_status": "GET"
}
}
# Validate API structure
if "endpoints" not in composer_api or "methods" not in composer_api:
print(" ❌ Composer API missing required sections")
return False
# Test blueprint submission workflow
workflow = [
"submit_blueprint",
"get_blueprint",
"start_compose",
"get_compose_status"
]
for step in workflow:
if step not in composer_api["methods"]:
print(f" ❌ Missing workflow step: {step}")
return False
print(" ✅ Composer integration patterns are valid")
return True
def main():
"""Main test function"""
print("Debian Atomic Blueprint System Test")
print("=" * 50)
tests = [
("Blueprint Structure", test_blueprint_structure),
("Blueprint Variants", test_blueprint_variants),
("Blueprint Variables", test_blueprint_variables),
("OSBuild Pipeline Integration", test_osbuild_pipeline_integration),
("Blueprint Validation", test_blueprint_validation),
("Composer Integration", test_composer_integration)
]
results = []
for test_name, test_func in tests:
try:
result = test_func()
results.append((test_name, result))
except Exception as e:
print(f"{test_name} test failed with exception: {e}")
results.append((test_name, False))
# Summary
print("\n" + "=" * 50)
print("TEST SUMMARY")
print("=" * 50)
passed = 0
total = len(results)
for test_name, result in results:
status = "✅ PASS" if result else "❌ FAIL"
print(f"{test_name}: {status}")
if result:
passed += 1
print(f"\nOverall: {passed}/{total} tests passed")
if passed == total:
print("🎉 All tests passed! Blueprint system is ready for composer integration.")
return 0
else:
print("⚠️ Some tests failed. Please review the issues above.")
return 1
if __name__ == '__main__':
sys.exit(main())