✨ NEW FEATURES: - Real container filesystem extraction using podman/docker - ContainerProcessor module for complete container analysis - Dynamic manifest generation based on real container content - Dual bootloader support (GRUB + bootupd) with auto-detection - Smart detection of OS, architecture, packages, and size 🔧 IMPROVEMENTS: - Moved from placeholder to real container processing - Container-aware debos manifest generation - Seamless integration between extraction and manifest creation - Production-ready container processing workflow 🧪 TESTING: - Container extraction test: debian:trixie-slim (78 packages, 78.72 MB) - Integration test: Working with real container images - Architecture detection: Auto-detects x86_64 from container content - OS detection: Auto-detects Debian 13 (trixie) from os-release 📊 PROGRESS: - Major milestone: Real container processing capability achieved - Ready for debos environment testing and end-to-end validation 📁 FILES: - New: container_processor.go, test-container-extraction.go - New: REAL_CONTAINER_EXTRACTION.md documentation - Updated: All integration modules, progress docs, README, todo, changelog 🚀 STATUS: Implementation complete - ready for testing!
110 lines
3.3 KiB
Go
110 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/particle-os/debian-bootc-image-builder/bib/internal/debos_integration"
|
|
)
|
|
|
|
func main() {
|
|
fmt.Println("🧪 Testing Real Container Extraction")
|
|
fmt.Println("====================================")
|
|
|
|
// Create work directory
|
|
workDir := "./test-container-extraction"
|
|
os.RemoveAll(workDir) // Clean up previous test
|
|
os.MkdirAll(workDir, 0755) // Create directory
|
|
|
|
// Create container processor
|
|
processor := debos_integration.NewContainerProcessor(workDir)
|
|
|
|
// Test container extraction
|
|
containerImage := "debian:trixie-slim" // Use a small image for testing
|
|
|
|
fmt.Printf("📦 Extracting container: %s\n", containerImage)
|
|
fmt.Printf(" Work directory: %s\n", workDir)
|
|
|
|
// Extract container
|
|
containerInfo, err := processor.ExtractContainer(containerImage)
|
|
if err != nil {
|
|
log.Fatalf("❌ Container extraction failed: %v", err)
|
|
}
|
|
|
|
fmt.Println("✅ Container extraction successful!")
|
|
fmt.Printf(" Working directory: %s\n", containerInfo.WorkingDir)
|
|
|
|
if containerInfo.OSRelease != nil {
|
|
fmt.Printf(" OS: %s %s\n", containerInfo.OSRelease.ID, containerInfo.OSRelease.VersionID)
|
|
}
|
|
|
|
if len(containerInfo.PackageList) > 0 {
|
|
fmt.Printf(" Packages found: %d\n", len(containerInfo.PackageList))
|
|
// Show first few packages
|
|
if len(containerInfo.PackageList) > 5 {
|
|
fmt.Printf(" Sample packages: %v\n", containerInfo.PackageList[:5])
|
|
} else {
|
|
fmt.Printf(" Packages: %v\n", containerInfo.PackageList)
|
|
}
|
|
}
|
|
|
|
if containerInfo.Size > 0 {
|
|
fmt.Printf(" Container size: %d bytes (%.2f MB)\n", containerInfo.Size, float64(containerInfo.Size)/1024/1024)
|
|
}
|
|
|
|
if len(containerInfo.Layers) > 0 {
|
|
fmt.Printf(" Container layers: %d\n", len(containerInfo.Layers))
|
|
fmt.Printf(" Sample layers: %v\n", containerInfo.Layers[:min(3, len(containerInfo.Layers))])
|
|
}
|
|
|
|
// List extracted files
|
|
fmt.Println("\n📁 Extracted files:")
|
|
if entries, err := os.ReadDir(containerInfo.WorkingDir); err == nil {
|
|
for _, entry := range entries {
|
|
if entry.IsDir() {
|
|
fmt.Printf(" 📁 %s/\n", entry.Name())
|
|
} else {
|
|
fmt.Printf(" 📄 %s\n", entry.Name())
|
|
}
|
|
}
|
|
}
|
|
|
|
// Test specific file extraction
|
|
fmt.Println("\n🔍 Testing specific file extraction:")
|
|
|
|
// Check for os-release
|
|
osReleasePath := filepath.Join(containerInfo.WorkingDir, "etc/os-release")
|
|
if data, err := os.ReadFile(osReleasePath); err == nil {
|
|
fmt.Printf(" ✅ os-release found: %s\n", string(data[:min(100, len(data))]))
|
|
} else {
|
|
fmt.Printf(" ❌ os-release not found: %v\n", err)
|
|
}
|
|
|
|
// Check for package list
|
|
dpkgStatusPath := filepath.Join(containerInfo.WorkingDir, "var/lib/dpkg/status")
|
|
if data, err := os.ReadFile(dpkgStatusPath); err == nil {
|
|
fmt.Printf(" ✅ dpkg status found: %d bytes\n", len(data))
|
|
} else {
|
|
fmt.Printf(" ❌ dpkg status not found: %v\n", err)
|
|
}
|
|
|
|
fmt.Println("\n🎉 Container extraction test completed successfully!")
|
|
fmt.Println("\n💡 Next steps:")
|
|
fmt.Println(" 1. Test with different container images")
|
|
fmt.Println(" 2. Integrate with manifest generation")
|
|
fmt.Println(" 3. Test end-to-end image building")
|
|
|
|
// Cleanup
|
|
if err := processor.Cleanup(containerInfo); err != nil {
|
|
fmt.Printf("⚠️ Cleanup warning: %v\n", err)
|
|
}
|
|
}
|
|
|
|
func min(a, b int) int {
|
|
if a < b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|