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
381 lines
12 KiB
Python
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())
|