#!/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())