debian-forge/test/debian/test-ostree-composition.py

302 lines
10 KiB
Python

#!/usr/bin/python3
"""
Test OSTree Composition for Debian Atomic
This script tests the OSTree composition functionality to ensure
Debian packages can be properly converted to atomic commits.
"""
import os
import sys
import subprocess
import tempfile
import json
import shutil
def test_ostree_availability():
"""Test if ostree is available and working"""
print("Testing OSTree availability...")
try:
result = subprocess.run(["ostree", "--version"],
capture_output=True, text=True, check=True)
print(f"✅ ostree is available: {result.stdout.strip()}")
return True
except subprocess.CalledProcessError as e:
print(f"❌ ostree command failed: {e}")
return False
except FileNotFoundError:
print("❌ ostree not found in PATH")
return False
def test_ostree_repo_creation():
"""Test OSTree repository creation"""
print("Testing OSTree repository creation...")
with tempfile.TemporaryDirectory() as temp_dir:
repo_path = os.path.join(temp_dir, "test-repo")
try:
# Create repository
result = subprocess.run(["ostree", "init", "--repo", repo_path],
capture_output=True, text=True, check=True)
print(f"✅ Repository created at {repo_path}")
# Check repository structure
if os.path.exists(os.path.join(repo_path, "config")):
print("✅ Repository config exists")
else:
print("❌ Repository config missing")
return False
return True
except subprocess.CalledProcessError as e:
print(f"❌ Repository creation failed: {e}")
print(f"stderr: {e.stderr}")
return False
def test_ostree_commit_creation():
"""Test OSTree commit creation from filesystem"""
print("Testing OSTree commit creation...")
with tempfile.TemporaryDirectory() as temp_dir:
repo_path = os.path.join(temp_dir, "test-repo")
tree_path = os.path.join(temp_dir, "test-tree")
try:
# Create repository
subprocess.run(["ostree", "init", "--repo", repo_path], check=True)
# Create test filesystem tree
os.makedirs(tree_path, exist_ok=True)
os.makedirs(os.path.join(tree_path, "etc"), exist_ok=True)
os.makedirs(os.path.join(tree_path, "usr"), exist_ok=True)
# Create test files
with open(os.path.join(tree_path, "etc", "test.conf"), "w") as f:
f.write("# Test configuration\n")
with open(os.path.join(tree_path, "usr", "test.txt"), "w") as f:
f.write("Test content\n")
# Create commit
cmd = [
"ostree", "commit",
"--repo", repo_path,
"--branch", "test/debian",
"--subject", "Test Debian commit",
tree_path
]
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
commit_hash = result.stdout.strip()
print(f"✅ Commit created: {commit_hash}")
# Verify commit exists
result = subprocess.run(["ostree", "show", "--repo", repo_path, commit_hash],
capture_output=True, text=True, check=True)
print("✅ Commit verification successful")
return True
except subprocess.CalledProcessError as e:
print(f"❌ Commit creation failed: {e}")
print(f"stderr: {e.stderr}")
return False
def test_debian_ostree_stage():
"""Test the Debian OSTree stage functionality"""
print("Testing Debian OSTree stage...")
# Check if stage file exists
stage_file = "stages/org.osbuild.ostree.commit.py"
if not os.path.exists(stage_file):
print(f"❌ Stage file not found: {stage_file}")
return False
print(f"✅ Stage file exists: {stage_file}")
# Check if metadata file exists
meta_file = "stages/org.osbuild.ostree.commit.meta.json"
if not os.path.exists(meta_file):
print(f"❌ Metadata file not found: {meta_file}")
return False
print(f"✅ Metadata file exists: {meta_file}")
# Validate metadata JSON
try:
with open(meta_file, 'r') as f:
metadata = json.load(f)
required_fields = ["name", "version", "description", "options"]
for field in required_fields:
if field not in metadata:
print(f"❌ Missing required field: {field}")
return False
print("✅ Metadata validation passed")
return True
except json.JSONDecodeError as e:
print(f"❌ Invalid JSON in metadata: {e}")
return False
except Exception as e:
print(f"❌ Metadata validation failed: {e}")
return False
def test_ostree_deploy_stage():
"""Test the OSTree deploy stage"""
print("Testing OSTree deploy stage...")
# Check if stage file exists
stage_file = "stages/org.osbuild.ostree.deploy.py"
if not os.path.exists(stage_file):
print(f"❌ Deploy stage file not found: {stage_file}")
return False
print(f"✅ Deploy stage file exists: {stage_file}")
# Check if metadata file exists
meta_file = "stages/org.osbuild.ostree.deploy.meta.json"
if not os.path.exists(meta_file):
print(f"❌ Deploy metadata file not found: {meta_file}")
return False
print(f"✅ Deploy metadata file exists: {meta_file}")
return True
def test_ostree_workflow():
"""Test complete OSTree workflow"""
print("Testing complete OSTree workflow...")
with tempfile.TemporaryDirectory() as temp_dir:
repo_path = os.path.join(temp_dir, "workflow-repo")
tree_path = os.path.join(temp_dir, "workflow-tree")
deploy_path = os.path.join(temp_dir, "workflow-deploy")
try:
# 1. Create repository
subprocess.run(["ostree", "init", "--repo", repo_path], check=True)
print("✅ Step 1: Repository created")
# 2. Create test filesystem
os.makedirs(tree_path, exist_ok=True)
os.makedirs(os.path.join(tree_path, "etc"), exist_ok=True)
os.makedirs(os.path.join(tree_path, "usr", "bin"), exist_ok=True)
# Create test files
with open(os.path.join(tree_path, "etc", "debian-version"), "w") as f:
f.write("12.0\n")
with open(os.path.join(tree_path, "usr", "bin", "test-app"), "w") as f:
f.write("#!/bin/bash\necho 'Debian Atomic Test'\n")
os.chmod(os.path.join(tree_path, "usr", "bin", "test-app"), 0o755)
print("✅ Step 2: Test filesystem created")
# 3. Create commit
cmd = [
"ostree", "commit",
"--repo", repo_path,
"--branch", "debian/atomic/test",
"--subject", "Debian Atomic Test Commit",
tree_path
]
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
commit_hash = result.stdout.strip()
print(f"✅ Step 3: Commit created: {commit_hash}")
# 4. Deploy commit
os.makedirs(deploy_path, exist_ok=True)
deploy_cmd = [
"ostree", "admin", "init-fs", "--modern", deploy_path
]
subprocess.run(deploy_cmd, check=True)
print("✅ Step 4: Deployment filesystem initialized")
# 5. Pull and deploy
pull_cmd = [
"ostree", "pull-local", repo_path, "debian/atomic/test",
"--repo", os.path.join(deploy_path, "ostree/repo")
]
subprocess.run(pull_cmd, check=True)
print("✅ Step 5: Commit pulled to deployment repo")
# 6. Initialize OS
os_init_cmd = [
"ostree", "admin", "os-init", "debian-atomic", deploy_path
]
subprocess.run(os_init_cmd, check=True)
print("✅ Step 6: OS initialized")
# 7. Deploy
deploy_cmd = [
"ostree", "admin", "deploy", "debian/atomic/test",
"--sysroot", deploy_path,
"--os", "debian-atomic"
]
subprocess.run(deploy_cmd, check=True)
print("✅ Step 7: Deployment completed")
# Verify deployment
stateroot = os.path.join(deploy_path, "ostree/deploy/debian-atomic")
if os.path.exists(stateroot):
print("✅ Step 8: Deployment verification successful")
return True
else:
print("❌ Step 8: Deployment verification failed")
return False
except subprocess.CalledProcessError as e:
print(f"❌ Workflow failed at step: {e}")
return False
def main():
"""Run all OSTree composition tests"""
print("OSTree Composition Tests for Debian Atomic")
print("=" * 50)
tests = [
("OSTree Availability", test_ostree_availability),
("Repository Creation", test_ostree_repo_creation),
("Commit Creation", test_ostree_commit_creation),
("Debian OSTree Stage", test_debian_ostree_stage),
("OSTree Deploy Stage", test_ostree_deploy_stage),
("Complete Workflow", test_ostree_workflow),
]
passed = 0
total = len(tests)
for test_name, test_func in tests:
print(f"\nRunning {test_name}...")
if test_func():
passed += 1
print()
print("=" * 50)
print(f"Test Results: {passed}/{total} passed")
if passed == total:
print("🎉 All OSTree composition tests passed!")
return 0
else:
print("❌ Some tests failed")
return 1
if __name__ == '__main__':
sys.exit(main())