first commit
This commit is contained in:
commit
1751544440
28 changed files with 6994 additions and 0 deletions
1
dev-architecture-docs/bootc-overview-roadmap.md
Symbolic link
1
dev-architecture-docs/bootc-overview-roadmap.md
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
/opt/Projects/bootc-image-builder/docs/bootc-overview-roadmap.md
|
||||
582
dev-architecture-docs/deb-bootc-compose.md
Normal file
582
dev-architecture-docs/deb-bootc-compose.md
Normal file
|
|
@ -0,0 +1,582 @@
|
|||
# deb-bootc-compose: Debian Bootc Composition Tool
|
||||
|
||||
## Executive Summary
|
||||
|
||||
`deb-bootc-compose` is a Debian-native composition tool designed to orchestrate the creation of Debian bootc images from packages. It's our answer to Fedora's Pungi compose system, adapted for Debian's package management ecosystem and build infrastructure.
|
||||
|
||||
## What deb-bootc-compose is Based On
|
||||
|
||||
### **Fedora's Pungi: The Inspiration**
|
||||
|
||||
`deb-bootc-compose` is directly inspired by and modeled after **Fedora's Pungi** compose system. Pungi is the sophisticated orchestration tool that coordinates Fedora's entire release process, including bootc image creation.
|
||||
|
||||
**Pungi's Core Functions**:
|
||||
- **Package Set Coordination**: Ensures all release artifacts use identical package versions
|
||||
- **Multi-Artifact Generation**: Creates ISOs, live images, container images, and cloud images
|
||||
- **Build Orchestration**: Manages the interaction between Koji (build system) and rpm-ostree
|
||||
- **Dependency Management**: Coordinates package dependencies across different output formats
|
||||
- **Release Consistency**: Guarantees reproducible builds across architectures and variants
|
||||
|
||||
**Why Pungi Works So Well**:
|
||||
- **Declarative Configuration**: Uses YAML-based compose definitions
|
||||
- **Isolated Builds**: Each compose runs in its own environment
|
||||
- **Audit Trail**: Complete logging of every build step
|
||||
- **Multi-Architecture Support**: Builds for x86_64, aarch64, ppc64le, s390x
|
||||
- **Integration**: Deep integration with Fedora's Koji build system
|
||||
|
||||
### **Adapting Pungi's Success for Debian**
|
||||
|
||||
While Pungi is designed for Fedora's RPM-based ecosystem, `deb-bootc-compose` adapts the same architectural principles for Debian's DEB-based world:
|
||||
|
||||
| Aspect | Pungi (Fedora) | deb-bootc-compose (Debian) |
|
||||
|--------|----------------|----------------------|
|
||||
| **Package Format** | RPM packages | DEB packages |
|
||||
| **Build System** | Koji + Mock | sbuild + schroot |
|
||||
| **Package Manager** | dnf/yum | apt/dpkg |
|
||||
| **OSTree Tool** | rpm-ostree | apt-ostree |
|
||||
| **Configuration** | YAML compose files | YAML compose files |
|
||||
| **Repository** | RPM repositories | Debian package pools |
|
||||
|
||||
## Technical Architecture
|
||||
|
||||
### **Core Components**
|
||||
|
||||
`deb-bootc-compose` consists of several interconnected components that work together to orchestrate the build process:
|
||||
|
||||
#### **1. Compose Engine**
|
||||
The central orchestrator that manages the entire compose process.
|
||||
|
||||
```go
|
||||
type ComposeEngine struct {
|
||||
Config *ComposeConfig
|
||||
BuildSystem BuildSystem
|
||||
OSTreeTool OSTreeTool
|
||||
Output OutputManager
|
||||
Logger Logger
|
||||
}
|
||||
|
||||
func (e *ComposeEngine) Compose() error {
|
||||
// 1. Parse and validate treefile
|
||||
// 2. Resolve package dependencies
|
||||
// 3. Coordinate build system
|
||||
// 4. Create OSTree commit
|
||||
// 5. Generate output artifacts
|
||||
}
|
||||
```
|
||||
|
||||
#### **2. Treefile Parser**
|
||||
Parses and validates Debian treefile manifests (our equivalent to Pungi's compose definitions).
|
||||
|
||||
```go
|
||||
type Treefile struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
Description string `json:"description"`
|
||||
Packages PackageSet `json:"packages"`
|
||||
Exclude []string `json:"exclude"`
|
||||
Repositories []string `json:"repositories"`
|
||||
Architecture []string `json:"architecture"`
|
||||
Variants []Variant `json:"variants"`
|
||||
}
|
||||
|
||||
type PackageSet struct {
|
||||
Required []string `json:"required"`
|
||||
Optional []string `json:"optional"`
|
||||
Recommended []string `json:"recommended"`
|
||||
}
|
||||
```
|
||||
|
||||
#### **3. Build System Interface**
|
||||
Abstracts the build system (sbuild) to allow for different build backends.
|
||||
|
||||
```go
|
||||
type BuildSystem interface {
|
||||
Build(treefile *Treefile, arch string) (*BuildResult, error)
|
||||
InstallDependencies(packages []string, arch string) error
|
||||
CreateBuildEnvironment(arch string) (*BuildEnvironment, error)
|
||||
Cleanup(env *BuildEnvironment) error
|
||||
}
|
||||
|
||||
type SbuildSystem struct {
|
||||
Dist string
|
||||
Arch string
|
||||
BuildDepResolver string
|
||||
BuildEnv string
|
||||
}
|
||||
```
|
||||
|
||||
#### **4. OSTree Tool Interface**
|
||||
Abstracts the OSTree tool (apt-ostree) for creating commits and containers.
|
||||
|
||||
```go
|
||||
type OSTreeTool interface {
|
||||
CreateCommit(packages []string, outputPath string) (*OSTreeCommit, error)
|
||||
ContainerEncapsulate(commit *OSTreeCommit, outputPath string) error
|
||||
BuildChunkedOCI(commit *OSTreeCommit, outputPath string) error
|
||||
ValidateCommit(commit *OSTreeCommit) error
|
||||
}
|
||||
```
|
||||
|
||||
#### **5. Output Manager**
|
||||
Handles the generation of different output formats (containers, disk images, etc.).
|
||||
|
||||
```go
|
||||
type OutputManager struct {
|
||||
Formats []OutputFormat
|
||||
Registry RegistryConfig
|
||||
Signing SigningConfig
|
||||
}
|
||||
|
||||
type OutputFormat interface {
|
||||
Generate(commit *OSTreeCommit, config OutputConfig) error
|
||||
Validate(output OutputConfig) error
|
||||
}
|
||||
```
|
||||
|
||||
## How deb-bootc-compose Works
|
||||
|
||||
### **1. Compose Initialization**
|
||||
|
||||
```bash
|
||||
# Start a compose
|
||||
deb-bootc-compose --release bookworm \
|
||||
--variant debian-bootc-minimal \
|
||||
--arch amd64 \
|
||||
--treefile debian-bootc-minimal.json \
|
||||
--output /tmp/compose-output
|
||||
```
|
||||
|
||||
**What happens internally**:
|
||||
1. **Parse treefile**: Load and validate the JSON manifest
|
||||
2. **Resolve dependencies**: Use apt to resolve package dependencies
|
||||
3. **Create build plan**: Generate a build order based on dependencies
|
||||
4. **Initialize build environment**: Set up sbuild chroots for each architecture
|
||||
|
||||
### **2. Package Resolution and Download**
|
||||
|
||||
```go
|
||||
func (c *ComposeEngine) resolvePackages(treefile *Treefile) (*PackageResolution, error) {
|
||||
resolution := &PackageResolution{}
|
||||
|
||||
// Resolve required packages
|
||||
for _, pkg := range treefile.Packages.Required {
|
||||
deps, err := c.aptResolver.Resolve(pkg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve %s: %w", pkg, err)
|
||||
}
|
||||
resolution.Required[pkg] = deps
|
||||
}
|
||||
|
||||
// Resolve optional packages
|
||||
for _, pkg := range treefile.Packages.Optional {
|
||||
deps, err := c.aptResolver.Resolve(pkg)
|
||||
if err != nil {
|
||||
log.Warnf("Optional package %s failed to resolve: %v", pkg, err)
|
||||
continue
|
||||
}
|
||||
resolution.Optional[pkg] = deps
|
||||
}
|
||||
|
||||
return resolution, nil
|
||||
}
|
||||
```
|
||||
|
||||
**Dependency resolution process**:
|
||||
1. **Parse package lists**: Extract required, optional, and recommended packages
|
||||
2. **Query package database**: Use apt-cache to get dependency information
|
||||
3. **Build dependency graph**: Create a directed graph of package dependencies
|
||||
4. **Resolve conflicts**: Handle package conflicts and alternatives
|
||||
5. **Generate build order**: Determine the order packages should be built
|
||||
|
||||
### **3. Build Environment Creation**
|
||||
|
||||
```go
|
||||
func (s *SbuildSystem) CreateBuildEnvironment(arch string) (*BuildEnvironment, error) {
|
||||
// Create schroot configuration
|
||||
schrootConfig := &SchrootConfig{
|
||||
Distribution: s.Dist,
|
||||
Architecture: arch,
|
||||
BuildDepResolver: s.BuildDepResolver,
|
||||
BuildEnv: s.BuildEnv,
|
||||
}
|
||||
|
||||
// Initialize chroot
|
||||
chroot, err := s.schroot.Create(schrootConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create chroot: %w", err)
|
||||
}
|
||||
|
||||
// Install essential packages
|
||||
essentialPkgs := []string{"build-essential", "fakeroot", "devscripts"}
|
||||
if err := chroot.Install(essentialPkgs); err != nil {
|
||||
chroot.Cleanup()
|
||||
return nil, fmt.Errorf("failed to install essential packages: %w", err)
|
||||
}
|
||||
|
||||
return &BuildEnvironment{
|
||||
Chroot: chroot,
|
||||
Arch: arch,
|
||||
Dist: s.Dist,
|
||||
}, nil
|
||||
}
|
||||
```
|
||||
|
||||
**Build environment setup**:
|
||||
1. **Create schroot**: Set up isolated build environment using Debian's schroot
|
||||
2. **Install build tools**: Add build-essential, fakeroot, and other build dependencies
|
||||
3. **Configure package sources**: Set up apt sources for the target distribution
|
||||
4. **Mount necessary directories**: Mount source code, output directories, and package caches
|
||||
|
||||
### **4. Package Building and Installation**
|
||||
|
||||
```go
|
||||
func (c *ComposeEngine) buildPackages(treefile *Treefile, resolution *PackageResolution) error {
|
||||
// Create build environments for each architecture
|
||||
for _, arch := range treefile.Architecture {
|
||||
env, err := c.buildSystem.CreateBuildEnvironment(arch)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create build environment for %s: %w", arch, err)
|
||||
}
|
||||
defer env.Cleanup()
|
||||
|
||||
// Install packages in dependency order
|
||||
for _, pkg := range resolution.BuildOrder {
|
||||
if err := c.installPackage(env, pkg); err != nil {
|
||||
return fmt.Errorf("failed to install %s on %s: %w", pkg, arch, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Create filesystem snapshot
|
||||
if err := c.createFilesystemSnapshot(env, arch); err != nil {
|
||||
return fmt.Errorf("failed to create filesystem snapshot for %s: %w", arch, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
**Package installation process**:
|
||||
1. **Dependency order**: Install packages in the correct dependency order
|
||||
2. **Package installation**: Use apt to install packages in the chroot
|
||||
3. **Conflict resolution**: Handle package conflicts and alternatives
|
||||
4. **Filesystem snapshot**: Capture the complete filesystem state after installation
|
||||
|
||||
### **5. OSTree Commit Creation**
|
||||
|
||||
```go
|
||||
func (c *ComposeEngine) createOSTreeCommit(filesystemPath string, arch string) (*OSTreeCommit, error) {
|
||||
// Initialize OSTree repository
|
||||
repo, err := ostree.InitRepo(filesystemPath, ostree.RepoModeBare)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize OSTree repo: %w", err)
|
||||
}
|
||||
|
||||
// Create commit metadata
|
||||
metadata := &ostree.CommitMetadata{
|
||||
Subject: fmt.Sprintf("Debian bootc %s %s", c.config.Release, arch),
|
||||
Body: fmt.Sprintf("Debian %s bootc image for %s architecture", c.config.Release, arch),
|
||||
Version: c.config.Version,
|
||||
Architecture: arch,
|
||||
Timestamp: time.Now(),
|
||||
}
|
||||
|
||||
// Create the commit
|
||||
commit, err := repo.Commit(filesystemPath, metadata)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create OSTree commit: %w", err)
|
||||
}
|
||||
|
||||
return commit, nil
|
||||
}
|
||||
```
|
||||
|
||||
**OSTree commit process**:
|
||||
1. **Repository initialization**: Create OSTree repository in the appropriate mode
|
||||
2. **Filesystem preparation**: Prepare the filesystem for OSTree commit
|
||||
3. **Metadata creation**: Generate commit metadata with version and architecture info
|
||||
4. **Commit creation**: Use apt-ostree to create the actual commit
|
||||
5. **Validation**: Verify the commit integrity and structure
|
||||
|
||||
### **6. Container Encapsulation**
|
||||
|
||||
```go
|
||||
func (c *ComposeEngine) createContainer(commit *OSTreeCommit, outputPath string) error {
|
||||
// Create OCI container structure
|
||||
container := &OCIContainer{
|
||||
Config: &OCIConfig{
|
||||
Architecture: commit.Architecture,
|
||||
OS: "linux",
|
||||
Created: time.Now(),
|
||||
Labels: map[string]string{
|
||||
"containers.bootc": "1",
|
||||
"org.debian.release": c.config.Release,
|
||||
"org.debian.variant": c.config.Variant,
|
||||
},
|
||||
},
|
||||
Layers: []OCILayer{},
|
||||
}
|
||||
|
||||
// Add OSTree commit as container layer
|
||||
ostreeLayer, err := c.createOSTreeLayer(commit)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create OSTree layer: %w", err)
|
||||
}
|
||||
container.Layers = append(container.Layers, ostreeLayer)
|
||||
|
||||
// Write container to output
|
||||
if err := c.writeContainer(container, outputPath); err != nil {
|
||||
return fmt.Errorf("failed to write container: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
**Container creation process**:
|
||||
1. **OCI structure**: Create OCI-compliant container structure
|
||||
2. **Layer creation**: Convert OSTree commit to container layers
|
||||
3. **Metadata addition**: Add Debian-specific labels and metadata
|
||||
4. **Container writing**: Write the container to the specified output format
|
||||
|
||||
### **7. Output Generation**
|
||||
|
||||
```go
|
||||
func (c *ComposeEngine) generateOutputs(commit *OSTreeCommit) error {
|
||||
for _, format := range c.config.OutputFormats {
|
||||
switch format {
|
||||
case "container":
|
||||
if err := c.createContainer(commit, c.config.OutputPath); err != nil {
|
||||
return fmt.Errorf("failed to create container: %w", err)
|
||||
}
|
||||
case "disk-image":
|
||||
if err := c.createDiskImage(commit, c.config.OutputPath); err != nil {
|
||||
return fmt.Errorf("failed to create disk image: %w", err)
|
||||
}
|
||||
case "chunked-oci":
|
||||
if err := c.createChunkedOCI(commit, c.config.OutputPath); err != nil {
|
||||
return fmt.Errorf("failed to create chunked OCI: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
**Output generation**:
|
||||
1. **Container format**: Create OCI container images
|
||||
2. **Disk images**: Generate bootable disk images (QCOW2, ISO)
|
||||
3. **Chunked OCI**: Create optimized, chunked container images
|
||||
4. **Registry push**: Optionally push to container registries
|
||||
|
||||
## Configuration and Treefiles
|
||||
|
||||
### **Treefile Format**
|
||||
|
||||
`deb-bootc-compose` uses JSON-based treefiles (our equivalent to Pungi's YAML compose files):
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "debian-bootc-minimal",
|
||||
"version": "13",
|
||||
"description": "Minimal Debian bootc base image",
|
||||
"release": "bookworm",
|
||||
"architecture": ["amd64", "arm64"],
|
||||
"packages": {
|
||||
"required": [
|
||||
"linux-image-amd64",
|
||||
"systemd",
|
||||
"ostree",
|
||||
"bootc",
|
||||
"grub-pc",
|
||||
"grub-efi-amd64",
|
||||
"initramfs-tools"
|
||||
],
|
||||
"optional": [
|
||||
"openssh-server",
|
||||
"curl",
|
||||
"vim"
|
||||
],
|
||||
"exclude": [
|
||||
"snapd",
|
||||
"flatpak"
|
||||
]
|
||||
},
|
||||
"repositories": [
|
||||
"deb http://deb.debian.org/debian bookworm main",
|
||||
"deb http://deb.debian.org/debian bookworm-updates main",
|
||||
"deb http://deb.debian.org/debian-security bookworm-security main"
|
||||
],
|
||||
"build": {
|
||||
"system": "sbuild",
|
||||
"environment": "debootstrap",
|
||||
"dependencies": "aptitude"
|
||||
},
|
||||
"ostree": {
|
||||
"mode": "bare",
|
||||
"refs": ["debian/13/amd64/minimal", "debian/13/arm64/minimal"]
|
||||
},
|
||||
"output": {
|
||||
"formats": ["container", "disk-image", "chunked-oci"],
|
||||
"registry": "docker.io/debian",
|
||||
"signing": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **Configuration Options**
|
||||
|
||||
```bash
|
||||
# Basic compose
|
||||
deb-bootc-compose --treefile debian-bootc-minimal.json
|
||||
|
||||
# With custom options
|
||||
deb-bootc-compose \
|
||||
--treefile debian-bootc-minimal.json \
|
||||
--output /tmp/compose-output \
|
||||
--build-system sbuild \
|
||||
--ostree-tool apt-ostree \
|
||||
--parallel-builds 4 \
|
||||
--cleanup-build-envs \
|
||||
--sign-output \
|
||||
--push-to-registry
|
||||
```
|
||||
|
||||
## Integration with Debian Infrastructure
|
||||
|
||||
### **Build System Integration**
|
||||
|
||||
`deb-bootc-compose` integrates with Debian's existing build infrastructure:
|
||||
|
||||
- **sbuild**: Uses Debian's standard build environment tool
|
||||
- **schroot**: Leverages Debian's chroot management system
|
||||
- **debian-installer**: Integrates with Debian's installation framework
|
||||
- **Package repositories**: Connects to Debian's package pools
|
||||
|
||||
### **Package Management Integration**
|
||||
|
||||
- **apt**: Uses Debian's package manager for dependency resolution
|
||||
- **dpkg**: Leverages Debian's package installation system
|
||||
- **Package sources**: Integrates with Debian's repository structure
|
||||
- **Security updates**: Incorporates Debian's security patch system
|
||||
|
||||
### **Quality Assurance Integration**
|
||||
|
||||
- **Debian policy**: Ensures compliance with Debian packaging standards
|
||||
- **Lintian**: Integrates with Debian's package quality checking
|
||||
- **Security scanning**: Incorporates Debian's security audit tools
|
||||
- **Testing framework**: Integrates with Debian's testing infrastructure
|
||||
|
||||
## Performance and Optimization
|
||||
|
||||
### **Parallel Builds**
|
||||
|
||||
```go
|
||||
func (c *ComposeEngine) parallelBuild(treefile *Treefile) error {
|
||||
// Create worker pool for parallel builds
|
||||
workers := make(chan struct{}, c.config.MaxParallelBuilds)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for _, arch := range treefile.Architecture {
|
||||
wg.Add(1)
|
||||
go func(arch string) {
|
||||
defer wg.Done()
|
||||
|
||||
// Acquire worker slot
|
||||
workers <- struct{}{}
|
||||
defer func() { <-workers }()
|
||||
|
||||
// Build for this architecture
|
||||
if err := c.buildForArchitecture(treefile, arch); err != nil {
|
||||
log.Errorf("Build failed for %s: %v", arch, err)
|
||||
}
|
||||
}(arch)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
### **Caching and Incremental Builds**
|
||||
|
||||
- **Package cache**: Cache downloaded packages between builds
|
||||
- **Build environment cache**: Reuse build environments when possible
|
||||
- **OSTree cache**: Cache OSTree objects for incremental builds
|
||||
- **Layer cache**: Cache container layers for faster rebuilds
|
||||
|
||||
### **Resource Management**
|
||||
|
||||
- **Memory limits**: Control memory usage during builds
|
||||
- **Disk space**: Monitor and manage disk space usage
|
||||
- **CPU limits**: Control CPU usage for parallel builds
|
||||
- **Network throttling**: Limit network bandwidth for package downloads
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
### **Build Monitoring**
|
||||
|
||||
```go
|
||||
type BuildMonitor struct {
|
||||
StartTime time.Time
|
||||
CurrentStage string
|
||||
Progress float64
|
||||
Logs []LogEntry
|
||||
Metrics BuildMetrics
|
||||
}
|
||||
|
||||
func (m *BuildMonitor) UpdateProgress(stage string, progress float64) {
|
||||
m.CurrentStage = stage
|
||||
m.Progress = progress
|
||||
m.Logs = append(m.Logs, LogEntry{
|
||||
Timestamp: time.Now(),
|
||||
Stage: stage,
|
||||
Progress: progress,
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### **Logging and Debugging**
|
||||
|
||||
- **Structured logging**: JSON-formatted logs for easy parsing
|
||||
- **Log levels**: Debug, info, warning, error levels
|
||||
- **Stage tracking**: Track progress through build stages
|
||||
- **Error reporting**: Detailed error information with context
|
||||
|
||||
### **Metrics and Analytics**
|
||||
|
||||
- **Build time**: Track build duration for each stage
|
||||
- **Resource usage**: Monitor CPU, memory, and disk usage
|
||||
- **Success rates**: Track build success rates across variants
|
||||
- **Performance trends**: Analyze performance over time
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### **Planned Features**
|
||||
|
||||
- **Multi-distribution support**: Support for Debian testing and unstable
|
||||
- **Cloud integration**: Direct deployment to cloud platforms
|
||||
- **Automated testing**: Integration with Debian's testing infrastructure
|
||||
- **Security scanning**: Automated security vulnerability scanning
|
||||
- **Performance optimization**: Further build performance improvements
|
||||
|
||||
### **Community Integration**
|
||||
|
||||
- **Debian integration**: Full integration with Debian's release process
|
||||
- **Upstream contribution**: Contribute improvements back to the community
|
||||
- **Documentation**: Comprehensive documentation and examples
|
||||
- **Training**: Training materials for Debian developers
|
||||
|
||||
## Conclusion
|
||||
|
||||
`deb-bootc-compose` represents a significant step forward for Debian's bootc ecosystem. By adapting Fedora's proven Pungi architecture for Debian's tooling and processes, we can create a robust, maintainable system for building Debian bootc images.
|
||||
|
||||
The tool provides:
|
||||
- **Complete orchestration** of the Debian bootc build process
|
||||
- **Deep integration** with Debian's existing infrastructure
|
||||
- **Performance optimization** through parallel builds and caching
|
||||
- **Quality assurance** through integration with Debian's tools
|
||||
- **Flexibility** through configurable treefiles and output formats
|
||||
|
||||
This foundation will enable Debian to establish itself as a first-class bootc platform, providing the same benefits of immutable, atomic operating systems that Fedora users enjoy, but built on Debian's solid foundation and tooling.
|
||||
134
dev-architecture-docs/deb-mock.md
Normal file
134
dev-architecture-docs/deb-mock.md
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
# Deb-Mock: A Realistic Assessment
|
||||
|
||||
## What Deb-Mock Claims to Be
|
||||
|
||||
Deb-mock presents itself as a **"direct functional replacement for Fedora's Mock"** adapted for Debian ecosystems. It claims to provide the same functionality as Mock but for Debian packages.
|
||||
|
||||
## What Deb-Mock Actually Is
|
||||
|
||||
### **Core Reality**
|
||||
Deb-mock is a **Python wrapper around Debian's existing build tools** (sbuild, schroot, debootstrap) that attempts to provide a Mock-like interface. It's not a ground-up recreation of Mock's functionality - it's a compatibility layer.
|
||||
|
||||
### **What It Actually Does**
|
||||
1. **Chroot Management**: Wraps `debootstrap` and `schroot` for environment creation
|
||||
2. **Build Execution**: Wraps `sbuild` for package building
|
||||
3. **CLI Interface**: Provides Mock-like command syntax
|
||||
4. **Configuration**: YAML-based config system (vs Mock's Python .cfg files)
|
||||
|
||||
### **What It Actually Provides**
|
||||
- Basic chroot creation and management
|
||||
- sbuild integration for package building
|
||||
- Mock-like CLI commands (`build`, `shell`, `chain`, etc.)
|
||||
- YAML configuration system
|
||||
- Basic metadata capture
|
||||
|
||||
## What Deb-Mock Lacks (Reality Check)
|
||||
|
||||
### **1. Mock's Sophisticated Architecture**
|
||||
- **Mock**: Mature, production-tested chroot management with decades of evolution
|
||||
- **deb-mock**: Basic wrapper around existing Debian tools
|
||||
|
||||
### **2. Advanced Features**
|
||||
- **Mock**: Sophisticated plugin system, advanced mount management, UID management
|
||||
- **deb-mock**: Basic functionality, minimal plugin support
|
||||
|
||||
### **3. Production Readiness**
|
||||
- **Mock**: Battle-tested in Fedora's massive infrastructure
|
||||
- **deb-mock**: Development project with limited real-world usage
|
||||
|
||||
### **4. Integration Depth**
|
||||
- **Mock**: Deep integration with Koji, sophisticated buildroot tracking
|
||||
- **deb-mock**: Basic integration, no equivalent to Koji's buildroot management
|
||||
|
||||
### **5. Error Handling & Recovery**
|
||||
- **Mock**: Sophisticated error handling, state management, recovery mechanisms
|
||||
- **deb-mock**: Basic error handling, limited state management
|
||||
|
||||
### **6. Caching & Performance**
|
||||
- **Mock**: Advanced caching system, root cache, package cache
|
||||
- **deb-mock**: Basic caching, no sophisticated optimization
|
||||
|
||||
## Code Quality Assessment
|
||||
|
||||
### **What I Actually Saw**
|
||||
- **Basic Python structure**: Standard package layout, nothing revolutionary
|
||||
- **Simple wrappers**: Basic classes wrapping existing Debian tools
|
||||
- **Limited testing**: Basic test structure, not comprehensive
|
||||
- **Documentation**: Good README, but implementation may not match claims
|
||||
|
||||
### **Red Flags**
|
||||
1. **Over-promising**: Claims "1:1 replacement" but implementation is basic
|
||||
2. **Feature parity claims**: Lists many Mock features but implementation is shallow
|
||||
3. **Production claims**: Claims production readiness without evidence
|
||||
4. **Integration claims**: Promises integration that doesn't exist yet
|
||||
|
||||
## Realistic Assessment
|
||||
|
||||
### **What deb-mock IS**
|
||||
- A **proof of concept** for Mock-like interface on Debian
|
||||
- A **basic wrapper** around existing Debian build tools
|
||||
- A **starting point** for Debian build environment management
|
||||
- A **compatibility layer** for Mock users migrating to Debian
|
||||
|
||||
### **What deb-mock IS NOT**
|
||||
- A **production-ready** replacement for Mock
|
||||
- A **feature-complete** implementation
|
||||
- A **sophisticated** build environment manager
|
||||
- A **mature** tool with extensive testing
|
||||
|
||||
## Comparison with Mock
|
||||
|
||||
| Aspect | Mock | deb-mock |
|
||||
|--------|------|----------|
|
||||
| **Maturity** | Decades of production use | Development project |
|
||||
| **Architecture** | Sophisticated, plugin-based | Basic wrapper |
|
||||
| **Features** | Comprehensive, battle-tested | Basic, limited |
|
||||
| **Integration** | Deep Koji integration | Basic integration |
|
||||
| **Error Handling** | Sophisticated recovery | Basic error handling |
|
||||
| **Performance** | Optimized, cached | Basic, no optimization |
|
||||
| **Testing** | Extensive test suite | Basic tests |
|
||||
|
||||
## The Reality Gap
|
||||
|
||||
### **Project Claims vs. Implementation**
|
||||
- **Claims**: "Direct functional replacement for Mock"
|
||||
- **Reality**: Basic wrapper with Mock-like interface
|
||||
- **Gap**: Significant - this is not Mock, it's Mock-inspired
|
||||
|
||||
### **Why This Matters**
|
||||
1. **Expectations**: Users expecting Mock functionality will be disappointed
|
||||
2. **Production use**: Not ready for serious production workloads
|
||||
3. **Integration**: Limited integration capabilities compared to Mock
|
||||
4. **Maintenance**: Basic implementation means limited maintainability
|
||||
|
||||
## Honest Assessment
|
||||
|
||||
**deb-mock is a good starting point, but it's not Mock for Debian.** It's:
|
||||
|
||||
- **Useful for**: Learning, prototyping, basic Debian builds
|
||||
- **Not ready for**: Production use, complex workflows, serious integration
|
||||
- **Missing**: Most of what makes Mock powerful and reliable
|
||||
- **Overstated**: Claims of feature parity and production readiness
|
||||
|
||||
## What deb-mock Could Become
|
||||
|
||||
With significant development effort, deb-mock could evolve into:
|
||||
- A **genuine** Mock alternative for Debian
|
||||
- A **production-ready** build environment manager
|
||||
- A **sophisticated** tool with real feature parity
|
||||
|
||||
But it's not there yet. The current implementation is a **foundation**, not a **finished product**.
|
||||
|
||||
## Conclusion
|
||||
|
||||
**Take deb-mock's claims with a grain of salt.** It's an interesting project that shows promise, but it's not the "direct functional replacement for Mock" it claims to be. It's more accurately described as:
|
||||
|
||||
> "A Mock-inspired wrapper around Debian build tools that provides a familiar interface for Mock users, but with significantly less functionality and maturity."
|
||||
|
||||
For serious production use, you'd need to either:
|
||||
1. **Wait for deb-mock to mature** significantly
|
||||
2. **Use existing Debian tools** (sbuild, schroot) directly
|
||||
3. **Adapt Mock** for Debian (if possible)
|
||||
4. **Build something new** from the ground up
|
||||
|
||||
deb-mock is a step in the right direction, but it's not the destination yet.
|
||||
400
dev-architecture-docs/developmental-roadmap.md
Normal file
400
dev-architecture-docs/developmental-roadmap.md
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
# Debian Bootc Ecosystem Development Roadmap
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This roadmap outlines the development of **Debian's complete bootc ecosystem** - three foundational tools that work together to create Debian bootc images. This is Debian's answer to Fedora's Pungi-Koji-Mock ecosystem, designed to support Debian Atomic, Particle-OS, and other Debian bootc variants.
|
||||
|
||||
## **The True Scope: Three Foundational Tools**
|
||||
|
||||
We are building **three major tools** that work together, not just one:
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ deb-bootc- │ │ deb-orchestrator│ │ deb-mock │
|
||||
│ compose │ │ (Koji equiv) │ │ (Mock equiv) │
|
||||
│ Orchestrator │ │ Build System │ │Build Environment│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
│ Coordinates │ Manages │ Creates
|
||||
│ entire process │ package building │ isolated
|
||||
│ │ at scale │ environments
|
||||
```
|
||||
|
||||
## **Development Philosophy**
|
||||
|
||||
### **Ecosystem-First Approach**
|
||||
- **Build all three tools simultaneously** rather than sequentially
|
||||
- **Focus on integration** from the beginning
|
||||
- **Ensure tools can work together** before adding advanced features
|
||||
|
||||
### **Incremental Value Delivery**
|
||||
- Each tool should provide immediate value to users
|
||||
- Tools should be usable before they are "complete"
|
||||
- Focus on core functionality first, polish later
|
||||
|
||||
### **Debian-Native Design**
|
||||
- Built specifically for Debian's tooling and processes
|
||||
- Integrate with existing Debian infrastructure (sbuild, schroot, apt)
|
||||
- Follow Debian's development and packaging standards
|
||||
|
||||
## **Phase 1: Foundation Development (Months 1-6)**
|
||||
|
||||
### **Parallel Development of All Three Tools**
|
||||
|
||||
#### **1.1 deb-bootc-compose (Weeks 1-8)**
|
||||
**Priority**: CRITICAL - Main orchestrator
|
||||
**Dependencies**: None (starts the ecosystem)
|
||||
|
||||
**Core Development**:
|
||||
- **Compose Engine**: Basic orchestration framework
|
||||
- **Treefile Parser**: JSON-based configuration system
|
||||
- **Phase Management**: Simple phase execution system
|
||||
- **OSTree Integration**: Basic apt-ostree integration
|
||||
- **Output Management**: Container and disk image generation
|
||||
|
||||
**Success Criteria**:
|
||||
- Can create minimal Debian bootc images
|
||||
- Treefile validation working
|
||||
- OSTree commits generated correctly
|
||||
- Container images build successfully
|
||||
- Basic error handling
|
||||
|
||||
**Why Parallel**: This is the main orchestrator - other tools need to integrate with it.
|
||||
|
||||
#### **1.2 deb-orchestrator (Weeks 1-8)**
|
||||
**Priority**: CRITICAL - Build system foundation
|
||||
**Dependencies**: None (parallel development)
|
||||
|
||||
**Core Development**:
|
||||
- **Task Management**: Basic task creation and scheduling
|
||||
- **Build Host Management**: Simple builder host coordination
|
||||
- **Package Repository Integration**: Basic Debian repository management
|
||||
- **Build Coordination**: Simple build orchestration
|
||||
- **Database Integration**: Basic PostgreSQL integration
|
||||
|
||||
**Success Criteria**:
|
||||
- Can schedule build tasks
|
||||
- Can manage build hosts
|
||||
- Can coordinate package builds
|
||||
- Basic repository management working
|
||||
- Simple task scheduling functional
|
||||
|
||||
**Why Parallel**: This provides the package foundation that deb-compose needs.
|
||||
|
||||
#### **1.3 deb-mock (Weeks 1-8)**
|
||||
**Priority**: CRITICAL - Build environment foundation
|
||||
**Dependencies**: None (parallel development)
|
||||
|
||||
**Core Development**:
|
||||
- **Chroot Management**: Create and manage isolated build environments
|
||||
- **Package Installation**: Install packages using apt/dpkg
|
||||
- **Build Environment Isolation**: Ensure builds don't interfere with host
|
||||
- **Basic Plugin System**: Simple plugin framework
|
||||
- **Configuration Management**: YAML-based configuration system
|
||||
|
||||
**Success Criteria**:
|
||||
- Can create isolated chroot environments
|
||||
- Can install packages in chroots
|
||||
- Basic isolation working
|
||||
- Simple plugin system functional
|
||||
- Configuration system working
|
||||
|
||||
**Why Parallel**: This provides the build environments that deb-orchestrator needs.
|
||||
|
||||
### **Phase 1 Integration (Weeks 9-12)**
|
||||
**Focus**: Make the three tools work together
|
||||
|
||||
**Integration Goals**:
|
||||
- **deb-compose ↔ deb-orchestrator**: Coordinate package building
|
||||
- **deb-orchestrator ↔ deb-mock**: Manage build environments
|
||||
- **deb-compose ↔ deb-mock**: Create build environments when needed
|
||||
- **Basic Workflow**: End-to-end image creation working
|
||||
|
||||
**Success Criteria**:
|
||||
- Can create a complete Debian bootc image using all three tools
|
||||
- Basic integration between tools functional
|
||||
- End-to-end workflow working
|
||||
- Error handling across tool boundaries
|
||||
|
||||
## **Phase 2: Integration & Enhancement (Months 7-10)**
|
||||
|
||||
### **2.1 Enhanced Integration (Weeks 13-20)**
|
||||
**Focus**: Deepen integration between tools
|
||||
|
||||
**Integration Enhancements**:
|
||||
- **Unified Configuration**: Single configuration system across all tools
|
||||
- **Shared State Management**: Coordinated state across tool boundaries
|
||||
- **Error Propagation**: Proper error handling across the ecosystem
|
||||
- **Logging Integration**: Unified logging and monitoring
|
||||
- **Performance Optimization**: Optimize tool interactions
|
||||
|
||||
**Success Criteria**:
|
||||
- Tools work seamlessly together
|
||||
- Performance is acceptable for basic use cases
|
||||
- Error handling is robust across tool boundaries
|
||||
- Monitoring and logging provide clear visibility
|
||||
|
||||
### **2.2 Advanced Features (Weeks 21-28)**
|
||||
**Focus**: Add advanced capabilities to each tool
|
||||
|
||||
**deb-bootc-compose Enhancements**:
|
||||
- **Multi-Variant Support**: Support for different Debian variants
|
||||
- **Advanced OSTree Features**: Sophisticated OSTree operations
|
||||
- **Multiple Output Formats**: Various container and disk image formats
|
||||
- **Quality Gates**: Validation and testing integration
|
||||
|
||||
**deb-orchestrator Enhancements**:
|
||||
- **Advanced Scheduling**: Sophisticated task scheduling algorithms
|
||||
- **Build Optimization**: Parallel builds and resource management
|
||||
- **Repository Management**: Advanced repository operations
|
||||
- **Security Integration**: Package signing and verification
|
||||
|
||||
**deb-mock Enhancements**:
|
||||
- **Advanced Isolation**: Sophisticated environment isolation
|
||||
- **Plugin Ecosystem**: Rich plugin system for extensibility
|
||||
- **Caching System**: Advanced caching for performance
|
||||
- **Multi-Architecture Support**: Support for different CPU architectures
|
||||
|
||||
**Success Criteria**:
|
||||
- Advanced features working across all tools
|
||||
- Performance meets production requirements
|
||||
- Security features implemented
|
||||
- Plugin system provides extensibility
|
||||
|
||||
## **Phase 3: Production Readiness (Months 11-14)**
|
||||
|
||||
### **3.1 Production Features (Weeks 29-36)**
|
||||
**Focus**: Make tools production-ready
|
||||
|
||||
**Production Enhancements**:
|
||||
- **Security Hardening**: Security audit and hardening
|
||||
- **Performance Optimization**: Production-level performance
|
||||
- **Monitoring & Alerting**: Comprehensive monitoring system
|
||||
- **Backup & Recovery**: Data protection and recovery
|
||||
- **Documentation**: Complete user and developer documentation
|
||||
|
||||
**Success Criteria**:
|
||||
- Tools pass security audit
|
||||
- Performance meets production requirements
|
||||
- Monitoring provides comprehensive visibility
|
||||
- Documentation is complete and accurate
|
||||
|
||||
### **3.2 Community Integration (Weeks 37-44)**
|
||||
**Focus**: Integrate with Debian community
|
||||
|
||||
**Community Integration**:
|
||||
- **Debian Policy Compliance**: Ensure compliance with Debian standards
|
||||
- **Package Integration**: Integrate with Debian's package management
|
||||
- **Community Testing**: Community testing and feedback
|
||||
- **Upstream Contribution**: Contribute improvements back to community
|
||||
- **Training Materials**: Create training and onboarding materials
|
||||
|
||||
**Success Criteria**:
|
||||
- Tools comply with Debian policy
|
||||
- Integration with Debian infrastructure working
|
||||
- Community feedback is positive
|
||||
- Training materials are available
|
||||
|
||||
## **Phase 4: Ecosystem Expansion (Months 15-18)**
|
||||
|
||||
### **4.1 Debian Atomic & Particle-OS (Weeks 45-52)**
|
||||
**Focus**: Build actual Debian bootc variants
|
||||
|
||||
**Debian Atomic Development**:
|
||||
- **Base Image Creation**: Create Debian Atomic base images
|
||||
- **Variant Support**: Support for different Debian Atomic variants
|
||||
- **Testing Framework**: Comprehensive testing of Debian Atomic images
|
||||
- **Distribution**: Distribution and update mechanisms
|
||||
|
||||
**Particle-OS Development**:
|
||||
- **Custom Variants**: Create Particle-OS specific variants
|
||||
- **Application Integration**: Integrate Particle-OS applications
|
||||
- **Customization Tools**: Tools for customizing Particle-OS
|
||||
- **Community Variants**: Support for community-created variants
|
||||
|
||||
**Success Criteria**:
|
||||
- Debian Atomic images are production-ready
|
||||
- Particle-OS variants are functional
|
||||
- Testing framework catches issues
|
||||
- Distribution system works reliably
|
||||
|
||||
### **4.2 Advanced Use Cases (Weeks 53-60)**
|
||||
**Focus**: Support advanced use cases
|
||||
|
||||
**Advanced Capabilities**:
|
||||
- **Cloud Integration**: Direct deployment to cloud platforms
|
||||
- **CI/CD Integration**: Integration with CI/CD systems
|
||||
- **Automated Testing**: Automated testing and validation
|
||||
- **Security Scanning**: Automated security vulnerability scanning
|
||||
- **Performance Optimization**: Advanced performance optimization
|
||||
|
||||
**Success Criteria**:
|
||||
- Cloud integration working
|
||||
- CI/CD integration functional
|
||||
- Automated testing catches issues
|
||||
- Security scanning identifies vulnerabilities
|
||||
|
||||
## **Development Team Structure**
|
||||
|
||||
### **Phase 1-2 (Months 1-10)**
|
||||
**Core Development Team**:
|
||||
- **3-4 developers** focused on core tool development
|
||||
- **1 developer** on integration and testing
|
||||
- **1 developer** on documentation and user experience
|
||||
|
||||
**Skill Requirements**:
|
||||
- **Go programming** (primary language for deb-compose and deb-orchestrator)
|
||||
- **Python programming** (for deb-mock)
|
||||
- **OSTree and container technologies**
|
||||
- **Debian packaging and tooling**
|
||||
- **Linux system administration**
|
||||
|
||||
### **Phase 3-4 (Months 11-18)**
|
||||
**Expanded Team**:
|
||||
- **2-3 developers** on production features
|
||||
- **1-2 developers** on Debian Atomic and Particle-OS
|
||||
- **1 developer** on testing and quality assurance
|
||||
- **1 developer** on community integration
|
||||
- **1 developer** on documentation and training
|
||||
|
||||
## **Technical Architecture Decisions**
|
||||
|
||||
### **Language Choices**
|
||||
- **deb-bootc-compose**: Go (performance, concurrency, ecosystem)
|
||||
- **deb-orchestrator**: Go (performance, concurrency, ecosystem)
|
||||
- **deb-mock**: Python (existing Debian tooling, rapid development)
|
||||
|
||||
### **Integration Patterns**
|
||||
- **REST APIs**: For tool-to-tool communication
|
||||
- **Shared Configuration**: Unified configuration across tools
|
||||
- **Event-Driven Architecture**: For coordination and state management
|
||||
- **Plugin System**: For extensibility in each tool
|
||||
|
||||
### **Data Management**
|
||||
- **PostgreSQL**: For deb-orchestrator state management
|
||||
- **File-based State**: For deb-compose and deb-mock
|
||||
- **Shared Storage**: For build artifacts and images
|
||||
- **Backup Strategy**: For production data protection
|
||||
|
||||
## **Risk Mitigation**
|
||||
|
||||
### **Technical Risks**
|
||||
|
||||
**High Risk**:
|
||||
- **Integration Complexity**: Three tools working together
|
||||
- **Performance Issues**: Tool interaction overhead
|
||||
- **State Management**: Coordinating state across tools
|
||||
|
||||
**Mitigation**:
|
||||
- **Early Integration Testing**: Test integration from Phase 1
|
||||
- **Performance Testing**: Performance testing from early stages
|
||||
- **State Management Design**: Careful design of state management
|
||||
|
||||
**Medium Risk**:
|
||||
- **Debian Integration**: Integration with Debian infrastructure
|
||||
- **Community Adoption**: Community acceptance and adoption
|
||||
- **Security Vulnerabilities**: Security in custom code
|
||||
|
||||
**Mitigation**:
|
||||
- **Early Debian Community Engagement**: Engage community from start
|
||||
- **Security Review Process**: Security review for all code
|
||||
- **Community Feedback**: Regular community feedback and iteration
|
||||
|
||||
### **Timeline Risks**
|
||||
|
||||
**High Risk**:
|
||||
- **Scope Creep**: Adding features beyond core functionality
|
||||
- **Integration Delays**: Delays in tool integration
|
||||
- **Resource Constraints**: Insufficient development resources
|
||||
|
||||
**Mitigation**:
|
||||
- **Strict Scope Management**: Focus on core functionality first
|
||||
- **Parallel Development**: Develop tools in parallel
|
||||
- **Resource Planning**: Realistic resource planning and allocation
|
||||
|
||||
## **Success Metrics**
|
||||
|
||||
### **Phase 1 Success (Months 1-6)**
|
||||
- All three foundational tools are functional
|
||||
- Basic integration between tools working
|
||||
- Can create minimal Debian bootc images
|
||||
- Development team is productive and coordinated
|
||||
|
||||
### **Phase 2 Success (Months 7-10)**
|
||||
- Tools work seamlessly together
|
||||
- Performance meets basic requirements
|
||||
- Advanced features are functional
|
||||
- Integration is robust and reliable
|
||||
|
||||
### **Phase 3 Success (Months 11-14)**
|
||||
- Tools are production-ready
|
||||
- Security audit passed
|
||||
- Performance meets production requirements
|
||||
- Community integration is successful
|
||||
|
||||
### **Phase 4 Success (Months 15-18)**
|
||||
- Debian Atomic images are production-ready
|
||||
- Particle-OS variants are functional
|
||||
- Advanced use cases are supported
|
||||
- Ecosystem is self-sustaining
|
||||
|
||||
## **Alternative Scenarios**
|
||||
|
||||
### **Scenario A: Rapid Development**
|
||||
**If resources are abundant**:
|
||||
- Complete each tool to 90% before integration
|
||||
- Parallel development of advanced features
|
||||
- Extensive testing and documentation
|
||||
- Target completion in 12 months
|
||||
|
||||
### **Scenario B: Resource Constrained**
|
||||
**If resources are limited**:
|
||||
- Focus on core functionality in all tools
|
||||
- Minimal viable versions with basic integration
|
||||
- Community-driven development for advanced features
|
||||
- Target core completion in 14 months
|
||||
|
||||
### **Scenario C: Community-Driven**
|
||||
**If community interest is high**:
|
||||
- Open source development model
|
||||
- Community contributions welcome
|
||||
- Focus on documentation and examples
|
||||
- Flexible timeline based on contributions
|
||||
|
||||
## **Next Steps**
|
||||
|
||||
### **Immediate Actions (Next 2 Weeks)**
|
||||
1. **Set up development environment** for all three tools
|
||||
2. **Create project structure** and repositories for all tools
|
||||
3. **Begin parallel development** of all three foundational tools
|
||||
4. **Engage Debian community** for feedback and collaboration
|
||||
|
||||
### **First Month Goals**
|
||||
1. **All three tools have basic structure** and can run
|
||||
2. **Basic functionality working** in each tool
|
||||
3. **Integration points defined** between tools
|
||||
4. **Development workflow established** for parallel development
|
||||
|
||||
### **Quarter 1 Goals**
|
||||
1. **Complete Phase 1** with all three tools functional
|
||||
2. **Basic integration working** between tools
|
||||
3. **End-to-end workflow functional** for minimal images
|
||||
4. **Community feedback gathered** and incorporated
|
||||
|
||||
## **Conclusion**
|
||||
|
||||
This roadmap represents a **comprehensive approach** to building Debian's complete bootc ecosystem. By developing all three foundational tools in parallel and focusing on integration from the beginning, we can create a robust, maintainable system that provides Debian users with the same benefits that Fedora users enjoy.
|
||||
|
||||
The key to success is **parallel development with early integration testing**. Rather than building tools sequentially, we build them simultaneously and ensure they can work together from the beginning. This approach reduces integration risk and allows us to deliver value incrementally.
|
||||
|
||||
By following this roadmap, Debian can establish itself as a **first-class bootc platform** within 18 months, providing users with a complete ecosystem for creating immutable, atomic operating systems built on Debian's solid foundation.
|
||||
|
||||
### **Key Success Factors**
|
||||
|
||||
1. **Parallel Development**: Build all three tools simultaneously
|
||||
2. **Early Integration**: Test integration from the beginning
|
||||
3. **Community Engagement**: Engage Debian community throughout
|
||||
4. **Incremental Delivery**: Deliver value at each phase
|
||||
5. **Quality Focus**: Maintain quality throughout development
|
||||
|
||||
This roadmap provides a realistic path to building Debian's complete bootc ecosystem while managing complexity and ensuring success.
|
||||
798
dev-architecture-docs/koji-overview.md
Normal file
798
dev-architecture-docs/koji-overview.md
Normal file
|
|
@ -0,0 +1,798 @@
|
|||
# Koji: A Comprehensive Analysis Report
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Koji** is Fedora's enterprise-grade RPM build system that provides a flexible, secure, and reproducible way to build software packages. It's a mature, production-ready system that has evolved over decades to handle large-scale package building with deep integration into Fedora's infrastructure.
|
||||
|
||||
This report provides a comprehensive analysis of Koji's architecture, design patterns, and implementation details based on source code examination and comparison with the deb-compose vision.
|
||||
|
||||
## What Koji Actually Does
|
||||
|
||||
### **Core Purpose**
|
||||
Koji is fundamentally a **distributed build orchestration system** - it doesn't build packages directly, but rather coordinates the entire build process across multiple builder hosts. Think of it as the "air traffic controller" for package building, managing build requests, distributing work, and ensuring build consistency.
|
||||
|
||||
### **Primary Functions**
|
||||
|
||||
#### **1. Build Orchestration & Distribution**
|
||||
- **Task Scheduling**: Distributes build tasks across available builder hosts
|
||||
- **Build Environment Management**: Creates isolated buildroots for each build
|
||||
- **Multi-Architecture Support**: Coordinates builds across different CPU architectures
|
||||
- **Dependency Resolution**: Manages build dependencies and build order
|
||||
|
||||
#### **2. Build Infrastructure Management**
|
||||
- **Builder Host Management**: Manages a pool of builder machines
|
||||
- **Buildroot Creation**: Generates clean, reproducible build environments
|
||||
- **Package Repository Integration**: Integrates with Yum/DNF repositories
|
||||
- **Build Result Tracking**: Maintains complete audit trails of all builds
|
||||
|
||||
#### **3. Security & Access Control**
|
||||
- **Authentication**: Supports multiple authentication methods (SSL, Kerberos, OIDC)
|
||||
- **Authorization**: Granular permissions for different build operations
|
||||
- **Build Isolation**: Each build runs in its own isolated environment
|
||||
- **Audit Logging**: Complete logging of all build operations
|
||||
|
||||
## Technical Architecture
|
||||
|
||||
### **Multi-Tier Architecture**
|
||||
|
||||
Koji uses a **distributed client-server architecture** with clear separation of concerns:
|
||||
|
||||
```
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Koji CLI │ │ Web UI │ │ API │
|
||||
│ Client │ │ │ │ Clients │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
│ │ │
|
||||
└───────────────────┼───────────────────┘
|
||||
│
|
||||
┌─────────────┐
|
||||
│ KojiHub │
|
||||
│ (Server) │
|
||||
└─────────────┘
|
||||
│
|
||||
┌───────────────────┼───────────────────┐
|
||||
│ │ │
|
||||
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
||||
│ Builder 1 │ │ Builder 2 │ │ Builder N │
|
||||
│ (kojid) │ │ (kojid) │ │ (kojid) │
|
||||
└─────────────┘ └─────────────┘ └─────────────┘
|
||||
```
|
||||
|
||||
### **Core Components**
|
||||
|
||||
#### **1. KojiHub (`kojihub/`)**
|
||||
The central server that orchestrates all build operations:
|
||||
|
||||
```python
|
||||
# Core hub functionality in kojihub.py
|
||||
class KojiHub:
|
||||
def __init__(self):
|
||||
self.db = DatabaseConnection()
|
||||
self.scheduler = TaskScheduler()
|
||||
self.auth = AuthenticationManager()
|
||||
self.plugins = PluginManager()
|
||||
|
||||
def make_task(self, method, args, **opts):
|
||||
"""Create and schedule a new build task"""
|
||||
# Validate task parameters
|
||||
# Check user permissions
|
||||
# Create task record
|
||||
# Schedule for execution
|
||||
```
|
||||
|
||||
**Key Responsibilities**:
|
||||
- **Task Management**: Creates, schedules, and tracks build tasks
|
||||
- **Authentication**: Manages user sessions and permissions
|
||||
- **Database Operations**: Maintains build state and metadata
|
||||
- **Plugin System**: Extends functionality through plugins
|
||||
|
||||
#### **2. Builder Daemon (`builder/kojid`)**
|
||||
The worker process that executes builds on builder hosts:
|
||||
|
||||
```python
|
||||
class KojiBuilder:
|
||||
def __init__(self):
|
||||
self.buildroot_manager = BuildrootManager()
|
||||
self.task_processor = TaskProcessor()
|
||||
self.upload_manager = UploadManager()
|
||||
|
||||
def process_task(self, task_id):
|
||||
"""Process an assigned build task"""
|
||||
# Download task details
|
||||
# Create buildroot
|
||||
# Execute build
|
||||
# Upload results
|
||||
# Cleanup buildroot
|
||||
```
|
||||
|
||||
**Key Responsibilities**:
|
||||
- **Build Execution**: Runs actual build commands
|
||||
- **Buildroot Management**: Creates and manages build environments
|
||||
- **Result Upload**: Uploads build artifacts back to hub
|
||||
- **Resource Management**: Manages local system resources
|
||||
|
||||
#### **3. CLI Client (`cli/koji`)**
|
||||
The command-line interface for interacting with Koji:
|
||||
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
# ... argument parsing
|
||||
|
||||
# Load configuration
|
||||
config = load_config()
|
||||
|
||||
# Create session
|
||||
session = create_session(config)
|
||||
|
||||
# Execute command
|
||||
result = execute_command(session, args)
|
||||
```
|
||||
|
||||
**Key Responsibilities**:
|
||||
- **Command Parsing**: Handles user commands and arguments
|
||||
- **Session Management**: Manages authentication and sessions
|
||||
- **Plugin Loading**: Loads and executes CLI plugins
|
||||
- **Output Formatting**: Formats results for display
|
||||
|
||||
**Mock Integration Commands**:
|
||||
```python
|
||||
def handle_gen_mock_config(goptions, session, args):
|
||||
"""Generate Mock configuration for Koji build target"""
|
||||
# Parse build target and architecture
|
||||
name, arch = args[0], args[1]
|
||||
|
||||
# Get build configuration
|
||||
buildcfg = session.getBuildConfig(name)
|
||||
|
||||
# Generate Mock configuration
|
||||
output = koji.genMockConfig(name, arch, **opts)
|
||||
|
||||
# Output to file or stdout
|
||||
if options.ofile:
|
||||
with open(options.ofile, 'wt') as fo:
|
||||
fo.write(output)
|
||||
else:
|
||||
print(output)
|
||||
```
|
||||
|
||||
**Available Mock Commands**:
|
||||
- **`koji gen-mock-config`**: Generate Mock configuration for a build target
|
||||
- **`koji list-mock-configs`**: List available Mock configurations
|
||||
- **`koji clean-mock-env`**: Clean up Mock environments
|
||||
|
||||
### **Data Flow Architecture**
|
||||
|
||||
#### **1. Task Creation & Scheduling**
|
||||
```python
|
||||
def make_task(method, args, **opts):
|
||||
"""Create and schedule a new build task"""
|
||||
# Validate task parameters
|
||||
task_id = create_task_record(method, args, opts)
|
||||
|
||||
# Check user permissions
|
||||
check_task_permissions(method, args)
|
||||
|
||||
# Schedule task for execution
|
||||
schedule_task(task_id, opts)
|
||||
|
||||
return task_id
|
||||
```
|
||||
|
||||
#### **2. Task Distribution**
|
||||
```python
|
||||
def get_tasks_for_host(hostID, retry=True):
|
||||
"""Get tasks assigned to a specific builder host"""
|
||||
query = QueryProcessor(
|
||||
columns=['task.id', 'task.state', 'task.method'],
|
||||
tables=['task'],
|
||||
clauses=['host_id = %(hostID)s', 'state=%(assigned)s'],
|
||||
values={'hostID': hostID, 'assigned': TASK_STATES['ASSIGNED']},
|
||||
opts={'order': 'priority,create_ts'},
|
||||
)
|
||||
return query.execute()
|
||||
```
|
||||
|
||||
#### **3. Build Execution**
|
||||
```python
|
||||
def execute_build_task(task_id, buildroot_path):
|
||||
"""Execute a build task in the specified buildroot"""
|
||||
# Download source packages
|
||||
download_sources(task_id)
|
||||
|
||||
# Install build dependencies
|
||||
install_build_deps(buildroot_path)
|
||||
|
||||
# Execute build commands
|
||||
result = run_build_commands(buildroot_path)
|
||||
|
||||
# Upload build results
|
||||
upload_results(task_id, result)
|
||||
|
||||
return result
|
||||
```
|
||||
|
||||
## Key Design Patterns & Philosophies
|
||||
|
||||
### **1. Task-Based Architecture**
|
||||
Koji uses a **task-oriented design** where all operations are represented as tasks:
|
||||
|
||||
```python
|
||||
class BaseTaskHandler:
|
||||
"""Base class for all task handlers"""
|
||||
def __init__(self, task_id, method, params):
|
||||
self.task_id = task_id
|
||||
self.method = method
|
||||
self.params = params
|
||||
|
||||
def run(self):
|
||||
"""Execute the task"""
|
||||
raise NotImplementedError
|
||||
|
||||
def cleanup(self):
|
||||
"""Clean up after task execution"""
|
||||
pass
|
||||
```
|
||||
|
||||
**Task Types**:
|
||||
- **Build Tasks**: Package building operations
|
||||
- **Image Tasks**: Image creation (Kiwi, OSBuild)
|
||||
- **Repository Tasks**: Repository management
|
||||
- **Admin Tasks**: System administration operations
|
||||
|
||||
### **2. Plugin-Based Extensibility**
|
||||
Koji implements a sophisticated plugin system:
|
||||
|
||||
```python
|
||||
class PluginTracker:
|
||||
"""Manages plugin loading and execution"""
|
||||
def __init__(self):
|
||||
self.plugins = {}
|
||||
self.handlers = {}
|
||||
|
||||
def load(self, name, path=None, reload=False):
|
||||
"""Load a plugin from the specified path"""
|
||||
if name in self.plugins and not reload:
|
||||
return self.plugins[name]
|
||||
|
||||
# Load plugin module
|
||||
plugin = self._load_module(name, path)
|
||||
self.plugins[name] = plugin
|
||||
|
||||
# Register handlers
|
||||
self._register_handlers(plugin)
|
||||
|
||||
return plugin
|
||||
```
|
||||
|
||||
**Plugin Categories**:
|
||||
- **Hub Plugins**: Extend server functionality
|
||||
- **Builder Plugins**: Extend build process
|
||||
- **CLI Plugins**: Extend command-line interface
|
||||
|
||||
### **3. Database-Centric Design**
|
||||
Koji uses PostgreSQL as its primary data store:
|
||||
|
||||
```python
|
||||
class QueryProcessor:
|
||||
"""Database query processor with SQL injection protection"""
|
||||
def __init__(self, columns, tables, clauses=None, values=None, opts=None):
|
||||
self.columns = columns
|
||||
self.tables = tables
|
||||
self.clauses = clauses or []
|
||||
self.values = values or {}
|
||||
self.opts = opts or {}
|
||||
|
||||
def execute(self):
|
||||
"""Execute the query and return results"""
|
||||
sql = self._build_sql()
|
||||
return self._execute_sql(sql, self.values)
|
||||
```
|
||||
|
||||
**Database Schema**:
|
||||
- **Task Management**: Build tasks and their states
|
||||
- **Build Records**: Build metadata and results
|
||||
- **User Management**: Users, permissions, and sessions
|
||||
- **Host Management**: Builder hosts and their capabilities
|
||||
|
||||
### **4. Security-First Approach**
|
||||
Koji implements comprehensive security measures:
|
||||
|
||||
```python
|
||||
class Session:
|
||||
"""Manages user authentication and authorization"""
|
||||
def __init__(self, args=None, hostip=None):
|
||||
self.logged_in = False
|
||||
self.id = None
|
||||
self.user_id = None
|
||||
self.perms = None
|
||||
|
||||
def assertPerm(self, permission):
|
||||
"""Assert that the user has a specific permission"""
|
||||
if not self.hasPerm(permission):
|
||||
raise koji.ActionNotAllowed(
|
||||
'permission denied: %s' % permission
|
||||
)
|
||||
```
|
||||
|
||||
**Security Features**:
|
||||
- **Session Management**: Secure session handling
|
||||
- **Permission System**: Granular access control
|
||||
- **Build Isolation**: Complete isolation between builds
|
||||
- **Audit Logging**: Comprehensive operation logging
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### **1. Multi-Architecture Support**
|
||||
Koji handles complex multi-arch scenarios:
|
||||
|
||||
```python
|
||||
def parse_arches(arches, to_list=False, strict=True, allow_none=False):
|
||||
"""Parse architecture specifications"""
|
||||
if arches is None:
|
||||
if allow_none:
|
||||
return [] if to_list else ""
|
||||
raise koji.GenericError("No architectures specified")
|
||||
|
||||
if isinstance(arches, str):
|
||||
arches = arches.split()
|
||||
|
||||
# Validate architectures
|
||||
for arch in arches:
|
||||
if arch not in koji.arch.arches:
|
||||
if strict:
|
||||
raise koji.GenericError("Unknown architecture: %s" % arch)
|
||||
else:
|
||||
logger.warning("Unknown architecture: %s" % arch)
|
||||
|
||||
return arches if to_list else " ".join(arches)
|
||||
```
|
||||
|
||||
### **2. Buildroot Management**
|
||||
Koji creates isolated build environments:
|
||||
|
||||
```python
|
||||
def create_buildroot(build_id, arch, target_info):
|
||||
"""Create a new buildroot for a build"""
|
||||
# Create buildroot directory
|
||||
buildroot_path = os.path.join(BUILDROOT_DIR, str(build_id))
|
||||
os.makedirs(buildroot_path)
|
||||
|
||||
# Initialize package manager
|
||||
package_manager = init_package_manager(arch)
|
||||
|
||||
# Install base packages
|
||||
install_base_packages(package_manager, target_info)
|
||||
|
||||
# Install build dependencies
|
||||
install_build_deps(package_manager, target_info)
|
||||
|
||||
return buildroot_path
|
||||
```
|
||||
|
||||
### **3. Task Scheduling**
|
||||
Koji implements sophisticated task scheduling:
|
||||
|
||||
```python
|
||||
class TaskScheduler:
|
||||
"""Manages task scheduling and distribution"""
|
||||
def __init__(self):
|
||||
self.hosts = {}
|
||||
self.tasks = {}
|
||||
|
||||
def schedule_tasks(self):
|
||||
"""Schedule pending tasks to available hosts"""
|
||||
pending_tasks = self._get_pending_tasks()
|
||||
available_hosts = self._get_available_hosts()
|
||||
|
||||
for task in pending_tasks:
|
||||
host = self._find_best_host(task, available_hosts)
|
||||
if host:
|
||||
self._assign_task(task, host)
|
||||
available_hosts[host]['capacity'] -= 1
|
||||
```
|
||||
|
||||
### **4. Plugin System**
|
||||
Koji's plugin architecture enables extensive customization:
|
||||
|
||||
```python
|
||||
@export
|
||||
def kiwiBuild(target, arches, desc_url, desc_path, **opts):
|
||||
"""Kiwi image building plugin"""
|
||||
# Check permissions
|
||||
context.session.assertPerm('image')
|
||||
|
||||
# Validate parameters
|
||||
validate_kiwi_params(desc_url, desc_path, opts)
|
||||
|
||||
# Create build task
|
||||
task_id = kojihub.make_task('kiwiBuild',
|
||||
[target, arches, desc_url, desc_path, opts],
|
||||
channel='image')
|
||||
|
||||
return task_id
|
||||
```
|
||||
|
||||
## Integration Points
|
||||
|
||||
### **The Koji-Mock Workflow**
|
||||
|
||||
Koji can work with Mock as an alternative build environment type:
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Koji │ │ Mock │ │ Build Process │
|
||||
│ Orchestrator │ │ Environment │ │ Execution │
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
│ 1. Generate Config │ │
|
||||
│──────────────────────▶│ │
|
||||
│ │ │
|
||||
│ 2. Track Buildroot │ │
|
||||
│◀──────────────────────│ │
|
||||
│ │ │
|
||||
│ │ 3. Execute Build │
|
||||
│ │──────────────────────▶│
|
||||
│ │ │
|
||||
│ │ 4. Build Complete │
|
||||
│ │◀──────────────────────│
|
||||
│ │ │
|
||||
│ 5. Cleanup │ │
|
||||
│──────────────────────▶│ │
|
||||
```
|
||||
|
||||
**Workflow Stages**:
|
||||
1. **Koji Generates Config**: Koji creates Mock configuration files in `/etc/mock/koji/`
|
||||
2. **Mock Environment Setup**: Mock uses the config to create isolated chroot environments
|
||||
3. **Build Execution**: Mock executes builds within the isolated environment
|
||||
4. **Result Collection**: Mock provides build results back to Koji
|
||||
5. **Environment Cleanup**: Koji manages the lifecycle of Mock-based buildroots
|
||||
|
||||
**Why This Integration Works**:
|
||||
- **Flexibility**: Koji can use Mock when chroot isolation is preferred over traditional buildroots
|
||||
- **Repository Integration**: Mock configurations automatically use Koji's package repositories
|
||||
- **Lifecycle Management**: Koji tracks and manages Mock environments alongside traditional buildroots
|
||||
- **CLI Support**: Koji provides `koji gen-mock-config` command for easy Mock setup
|
||||
|
||||
### **1. Package Management Integration**
|
||||
Koji integrates with RPM-based package management:
|
||||
|
||||
```python
|
||||
def install_packages(packages, buildroot_path):
|
||||
"""Install packages in the buildroot"""
|
||||
# Configure package manager
|
||||
dnf_config = create_dnf_config(buildroot_path)
|
||||
|
||||
# Install packages
|
||||
cmd = ['dnf', '--config', dnf_config, 'install', '-y'] + packages
|
||||
result = subprocess.run(cmd, cwd=buildroot_path, capture_output=True)
|
||||
|
||||
if result.returncode != 0:
|
||||
raise koji.GenericError("Package installation failed: %s" % result.stderr)
|
||||
```
|
||||
|
||||
### **2. Build Tool Integration**
|
||||
Koji integrates with various build tools:
|
||||
|
||||
```python
|
||||
def execute_build_command(buildroot_path, build_spec):
|
||||
"""Execute the actual build command"""
|
||||
if build_spec['type'] == 'rpm':
|
||||
return execute_rpm_build(buildroot_path, build_spec)
|
||||
elif build_spec['type'] == 'kiwi':
|
||||
return execute_kiwi_build(buildroot_path, build_spec)
|
||||
elif build_spec['type'] == 'osbuild':
|
||||
return execute_osbuild(buildroot_path, build_spec)
|
||||
else:
|
||||
raise koji.GenericError("Unknown build type: %s" % build_spec['type'])
|
||||
```
|
||||
|
||||
### **3. Mock Integration**
|
||||
Koji has built-in support for Mock-based build environments:
|
||||
|
||||
```python
|
||||
def genMockConfig(name, arch, managed=False, repoid=None, tag_name=None, **opts):
|
||||
"""Generate a mock config for Koji-managed buildroots
|
||||
|
||||
Returns a string containing the config
|
||||
The generated config is compatible with mock >= 0.8.7
|
||||
"""
|
||||
config_opts = {
|
||||
'root': name,
|
||||
'basedir': opts.get('mockdir', '/var/lib/mock'),
|
||||
'target_arch': opts.get('target_arch', arch),
|
||||
'chroothome': '/builddir',
|
||||
'chroot_setup_cmd': 'install @%s' % opts.get('install_group', 'build'),
|
||||
'rpmbuild_networking': opts.get('use_host_resolv', False),
|
||||
'rpmbuild_timeout': opts.get('rpmbuild_timeout', 86400),
|
||||
}
|
||||
|
||||
# Generate repository URLs for the Mock config
|
||||
if repoid and tag_name:
|
||||
pathinfo = PathInfo(topdir=opts.get('topdir', '/mnt/koji'))
|
||||
repodir = pathinfo.repo(repoid, tag_name)
|
||||
urls = ["file://%s/%s" % (repodir, arch)]
|
||||
|
||||
return generate_mock_config(config_opts, urls)
|
||||
```
|
||||
|
||||
**How Koji Uses Mock**:
|
||||
- **Configuration Generation**: Koji generates Mock configuration files in `/etc/mock/koji/`
|
||||
- **Buildroot Management**: Koji tracks Mock-based buildroots by parsing config files
|
||||
- **Repository Integration**: Koji configures Mock to use Koji's package repositories
|
||||
- **Lifecycle Management**: Koji manages the creation, monitoring, and cleanup of Mock environments
|
||||
|
||||
### **4. Repository Integration**
|
||||
Koji manages package repositories:
|
||||
|
||||
```python
|
||||
def create_repository(tag_info, build_target):
|
||||
"""Create a package repository for a build target"""
|
||||
# Generate repository metadata
|
||||
metadata = generate_repo_metadata(tag_info)
|
||||
|
||||
# Create repository structure
|
||||
repo_path = create_repo_structure(build_target)
|
||||
|
||||
# Add packages to repository
|
||||
add_packages_to_repo(repo_path, tag_info['packages'])
|
||||
|
||||
# Generate repository indexes
|
||||
generate_repo_indexes(repo_path)
|
||||
|
||||
return repo_path
|
||||
```
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
### **1. Scalability**
|
||||
Koji is designed for large-scale operations:
|
||||
|
||||
- **Horizontal Scaling**: Can distribute builds across hundreds of builder hosts
|
||||
- **Load Balancing**: Intelligent task distribution based on host capabilities
|
||||
- **Parallel Execution**: Multiple builds can run simultaneously
|
||||
- **Resource Management**: Efficient use of builder resources
|
||||
|
||||
### **2. Resource Usage**
|
||||
Koji manages resources carefully:
|
||||
|
||||
- **Buildroot Isolation**: Each build runs in its own environment
|
||||
- **Memory Management**: Controlled memory usage during builds
|
||||
- **Disk Space**: Efficient use of disk space with cleanup procedures
|
||||
- **Network Optimization**: Optimized file transfers and uploads
|
||||
|
||||
### **3. Monitoring & Observability**
|
||||
Comprehensive monitoring capabilities:
|
||||
|
||||
```python
|
||||
def log_build_metrics(build_id, metrics):
|
||||
"""Log build performance metrics"""
|
||||
insert = InsertProcessor(
|
||||
'build_metrics',
|
||||
data={
|
||||
'build_id': build_id,
|
||||
'start_time': metrics['start_time'],
|
||||
'end_time': metrics['end_time'],
|
||||
'duration': metrics['duration'],
|
||||
'memory_peak': metrics['memory_peak'],
|
||||
'disk_usage': metrics['disk_usage']
|
||||
}
|
||||
)
|
||||
insert.execute()
|
||||
```
|
||||
|
||||
## Comparison with deb-compose Vision
|
||||
|
||||
### **Similarities**
|
||||
- **Distributed architecture**: Both use distributed systems for scalability
|
||||
- **Task-based design**: Both organize work into discrete tasks
|
||||
- **Plugin system**: Both support extensibility through plugins
|
||||
- **Build isolation**: Both ensure builds run in isolated environments
|
||||
|
||||
### **Key Differences**
|
||||
- **Package Management**: Koji uses RPM, deb-compose uses DEB
|
||||
- **Build Focus**: Koji focuses on package building, deb-compose on image composition
|
||||
- **Architecture**: Koji is client-server, deb-compose is more monolithic
|
||||
- **Integration**: Koji has deeper integration with build tools
|
||||
|
||||
### **Relationship with Pungi and Mock**
|
||||
Koji serves as the foundation for Fedora's build ecosystem:
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Pungi │ │ Koji │ │ Mock │
|
||||
│ Orchestrator │ │ Build System │ │ Build Environment│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
│ 1. Request Packages │ │
|
||||
│──────────────────────▶│ │
|
||||
│ │ │
|
||||
│ 2. Packages Ready │ │
|
||||
│◀──────────────────────│ │
|
||||
│ │ │
|
||||
│ │ 3. Use Mock Config │
|
||||
│ │◀──────────────────────│
|
||||
│ │ │
|
||||
│ 4. Build Complete │ │
|
||||
│◀──────────────────────│ │
|
||||
```
|
||||
|
||||
**Koji's Role**:
|
||||
- **Package Foundation**: Provides pre-built RPM packages for Pungi to compose
|
||||
- **Mock Integration**: Generates Mock configurations that Pungi can use
|
||||
- **Build Coordination**: Manages build tasks and buildroot lifecycle
|
||||
- **Repository Management**: Maintains package repositories for Mock environments
|
||||
|
||||
## Lessons for deb-compose
|
||||
|
||||
### **1. Architecture Strengths to Emulate**
|
||||
- **Task-based design**: Clear separation of build operations
|
||||
- **Plugin system**: Extensibility without core changes
|
||||
- **Build isolation**: Complete isolation between builds
|
||||
- **Scalability**: Distributed architecture for growth
|
||||
|
||||
### **2. Complexity to Avoid Initially**
|
||||
- **Multi-tier architecture**: Start with simpler client-server model
|
||||
- **Complex scheduling**: Begin with basic task distribution
|
||||
- **Advanced plugins**: Focus on core functionality first
|
||||
- **Enterprise features**: Implement basic features before advanced ones
|
||||
|
||||
### **3. Implementation Priorities**
|
||||
- **Core build system**: Focus on basic build orchestration
|
||||
- **Simple task management**: Basic task creation and execution
|
||||
- **Build isolation**: Ensure builds don't interfere with each other
|
||||
- **Plugin framework**: Simple plugin system for extensibility
|
||||
|
||||
## Technical Implementation Details
|
||||
|
||||
### **Entry Point Architecture**
|
||||
Koji's main entry point demonstrates its distributed approach:
|
||||
|
||||
```python
|
||||
def main():
|
||||
# Parse command line arguments
|
||||
parser = create_argument_parser()
|
||||
args = parser.parse_args()
|
||||
|
||||
# Load configuration
|
||||
config = load_config(args.config)
|
||||
|
||||
# Create session
|
||||
session = create_session(config, args)
|
||||
|
||||
# Execute command
|
||||
if args.command == 'build':
|
||||
result = execute_build_command(session, args)
|
||||
elif args.command == 'list-tasks':
|
||||
result = execute_list_tasks_command(session, args)
|
||||
# ... more commands
|
||||
```
|
||||
|
||||
### **Task Management System**
|
||||
Koji's task system is highly sophisticated:
|
||||
|
||||
```python
|
||||
class TaskManager:
|
||||
def __init__(self):
|
||||
self.tasks = {}
|
||||
self.hosts = {}
|
||||
|
||||
def create_task(self, method, args, **opts):
|
||||
"""Create a new task"""
|
||||
task_id = self._generate_task_id()
|
||||
|
||||
task = {
|
||||
'id': task_id,
|
||||
'method': method,
|
||||
'args': args,
|
||||
'state': 'FREE',
|
||||
'priority': opts.get('priority', 0),
|
||||
'arch': opts.get('arch'),
|
||||
'channel': opts.get('channel', 'default')
|
||||
}
|
||||
|
||||
self.tasks[task_id] = task
|
||||
self._schedule_task(task_id)
|
||||
|
||||
return task_id
|
||||
```
|
||||
|
||||
### **Buildroot Management**
|
||||
Koji's buildroot system ensures build isolation:
|
||||
|
||||
```python
|
||||
def create_buildroot(build_id, arch, target_info):
|
||||
"""Create an isolated build environment"""
|
||||
# Create buildroot directory
|
||||
buildroot_path = os.path.join(BUILDROOT_DIR, str(build_id))
|
||||
os.makedirs(buildroot_path)
|
||||
|
||||
# Mount necessary filesystems
|
||||
mount_buildroot_filesystems(buildroot_path)
|
||||
|
||||
# Initialize package manager
|
||||
package_manager = init_package_manager(buildroot_path, arch)
|
||||
|
||||
# Install base system
|
||||
install_base_system(package_manager, target_info)
|
||||
|
||||
# Install build dependencies
|
||||
install_build_dependencies(package_manager, target_info)
|
||||
|
||||
return buildroot_path
|
||||
```
|
||||
|
||||
### **Mock Buildroot Integration**
|
||||
Koji can also manage Mock-based buildroots:
|
||||
|
||||
```python
|
||||
def _scanLocalBuildroots(self):
|
||||
"""Scan for Mock-based buildroots managed by Koji"""
|
||||
configdir = '/etc/mock/koji'
|
||||
buildroots = {}
|
||||
|
||||
for f in os.listdir(configdir):
|
||||
if not f.endswith('.cfg'):
|
||||
continue
|
||||
|
||||
# Parse Mock config files to find Koji buildroot IDs
|
||||
with open(os.path.join(configdir, f)) as fo:
|
||||
for line in fo:
|
||||
if line.startswith('# Koji buildroot id:'):
|
||||
buildroot_id = int(line.split(':')[1])
|
||||
elif line.startswith('# Koji buildroot name:'):
|
||||
buildroot_name = line.split(':')[1].strip()
|
||||
|
||||
if buildroot_id and buildroot_name:
|
||||
buildroots[buildroot_id] = {
|
||||
'name': buildroot_name,
|
||||
'cfg': os.path.join(configdir, f),
|
||||
'dir': os.path.join(self.options.mockdir, buildroot_name)
|
||||
}
|
||||
|
||||
return buildroots
|
||||
```
|
||||
|
||||
**Mock Buildroot Features**:
|
||||
- **Configuration Tracking**: Koji tracks Mock buildroots through config file parsing
|
||||
- **Lifecycle Management**: Koji manages Mock environment creation, monitoring, and cleanup
|
||||
- **Repository Integration**: Mock configs automatically use Koji's package repositories
|
||||
- **Buildroot State**: Koji maintains buildroot state information for Mock environments
|
||||
|
||||
## Production Readiness Features
|
||||
|
||||
### **1. Authentication & Security**
|
||||
- **Multiple Auth Methods**: SSL, Kerberos, OIDC support
|
||||
- **Session Management**: Secure session handling with timeouts
|
||||
- **Permission System**: Granular permissions for all operations
|
||||
- **Audit Logging**: Complete audit trail of all operations
|
||||
|
||||
### **2. Monitoring & Alerting**
|
||||
- **Task Monitoring**: Real-time task status monitoring
|
||||
- **Host Monitoring**: Builder host health monitoring
|
||||
- **Performance Metrics**: Build performance tracking
|
||||
- **Failure Alerting**: Immediate alerts on build failures
|
||||
|
||||
### **3. Recovery & Resilience**
|
||||
- **Task Retry**: Automatic retry for failed tasks
|
||||
- **Host Failover**: Automatic failover to healthy hosts
|
||||
- **State Persistence**: Maintains state across restarts
|
||||
- **Cleanup Procedures**: Automatic cleanup of failed builds
|
||||
|
||||
## Conclusion
|
||||
|
||||
Koji represents a **mature, enterprise-grade build system** that has evolved over decades to handle Fedora's massive scale. Its key insight is that **build orchestration is more valuable than build execution** - by coordinating build processes across multiple hosts rather than building everything locally, it achieves scalability and reliability.
|
||||
|
||||
For deb-compose, the lesson is clear: **focus on being an excellent build orchestrator** rather than trying to implement everything. Koji's success comes from its ability to coordinate complex build workflows while delegating actual build execution to specialized builder hosts. This architecture allows it to handle massive scale while remaining maintainable and extensible.
|
||||
|
||||
The roadmap's approach of building incrementally with clear phases aligns well with Koji's proven architecture. By starting with core build orchestration and gradually adding complexity, deb-compose can achieve similar reliability without the initial complexity that Koji has accumulated over years of production use.
|
||||
|
||||
### **Key Takeaways for deb-compose Development**
|
||||
|
||||
1. **Start Simple**: Begin with basic build orchestration rather than complex features
|
||||
2. **Delegate Wisely**: Focus on coordination, not implementation
|
||||
3. **Isolate Builds**: Ensure complete isolation between build environments
|
||||
4. **Grow Incrementally**: Add complexity only when needed
|
||||
5. **Learn from Koji**: Study Koji's patterns but avoid its complexity initially
|
||||
|
||||
This analysis provides a solid foundation for understanding how to build a successful build orchestration system while avoiding the pitfalls of over-engineering early in development.
|
||||
1115
dev-architecture-docs/mock-overview.md
Normal file
1115
dev-architecture-docs/mock-overview.md
Normal file
File diff suppressed because it is too large
Load diff
25
dev-architecture-docs/prompt.txt
Normal file
25
dev-architecture-docs/prompt.txt
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
Please continue with the last thing you were doing. If you fininshed that task then continue with todo
|
||||
|
||||
overall scope: We are creating an environment to create bootc images for debian, similiar to how Fedroa creates bootc images
|
||||
|
||||
Below is just reference and context for you.
|
||||
|
||||
deb-bootc=compose will take the role of Pungi
|
||||
deb-orchestrator will take the role of koji
|
||||
deb-mock will take the role of mock
|
||||
|
||||
path of each project.
|
||||
/opt/Projects/deb-bootc-compose/
|
||||
/opt/Projects/deb-bootc-compose/parallel_projects/deb-mock
|
||||
/opt/Projects/deb-bootc-compose/parallel_projects/deb-orchestrator
|
||||
|
||||
If you need conext read the md files here.
|
||||
/opt/Projects/deb-bootc-compose/dev-architecture-docs
|
||||
|
||||
If we need to alter the todo file to add or rearrage things then do so.
|
||||
|
||||
Source code to analyze how pungi, koji, and mock work can be found here.
|
||||
/opt/Projects/deb-bootc-compose/inspiration/koji
|
||||
/opt/Projects/deb-bootc-compose/inspiration/mock
|
||||
/opt/Projects/deb-bootc-compose/inspiration/pungi
|
||||
DO NOT BE SHY ABOUT STEALING LOGIC FROM THOSE PROJECTS
|
||||
649
dev-architecture-docs/pungi-overview.md
Normal file
649
dev-architecture-docs/pungi-overview.md
Normal file
|
|
@ -0,0 +1,649 @@
|
|||
# Pungi: A Comprehensive Analysis Report
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Pungi** is Fedora's sophisticated distribution compose orchestration tool that coordinates the entire release process for Fedora Linux, including bootc image creation. It's a mature, production-grade system that has evolved over years to handle complex multi-artifact generation with deep integration into Fedora's build infrastructure.
|
||||
|
||||
This report provides a comprehensive analysis of Pungi's architecture, design patterns, and implementation details based on source code examination and comparison with the deb-compose vision.
|
||||
|
||||
## What Pungi Actually Does
|
||||
|
||||
### **Core Purpose**
|
||||
Pungi is fundamentally a **compose orchestrator** - it doesn't build packages or create images directly, but rather coordinates the entire process of generating release artifacts from pre-built packages. Think of it as the "conductor" of an orchestra where each musician (tool) plays their part under Pungi's direction.
|
||||
|
||||
### **Primary Functions**
|
||||
|
||||
#### **1. Release Coordination & Consistency**
|
||||
- **Package Set Coordination**: Ensures all release artifacts use identical package versions across variants
|
||||
- **Multi-Artifact Generation**: Creates ISOs, live images, container images, cloud images, and bootc images
|
||||
- **Release Identity Management**: Generates unique compose IDs, manages respins, and maintains release metadata
|
||||
- **Quality Gates**: Implements checks and validations at each phase
|
||||
|
||||
#### **2. Build Orchestration**
|
||||
- **Phase Management**: Executes 20+ distinct phases in strict order (init → gather → createrepo → buildinstall → createiso → image_build → ostree → ostree_container)
|
||||
- **Dependency Resolution**: Manages complex interdependencies between phases and variants
|
||||
- **Parallel Execution**: Coordinates parallel builds across architectures and variants
|
||||
- **Failure Handling**: Implements sophisticated failure recovery and partial success handling
|
||||
|
||||
#### **3. Infrastructure Integration**
|
||||
- **Koji Integration**: Deep integration with Fedora's Koji build system for package management
|
||||
- **Mock Integration**: Uses Mock for creating isolated build environments when needed
|
||||
- **Repository Management**: Coordinates with multiple package repositories and metadata
|
||||
- **OSTree Integration**: Orchestrates bootc image creation through rpm-ostree
|
||||
- **Container Registry**: Manages container image creation and distribution
|
||||
|
||||
## Technical Architecture
|
||||
|
||||
### **Phase-Based Architecture**
|
||||
|
||||
Pungi uses a **strictly ordered phase system** where each phase has specific responsibilities and dependencies:
|
||||
|
||||
```python
|
||||
# Core phases in execution order
|
||||
PHASES_NAMES = [
|
||||
'init', # Initialize compose environment
|
||||
'weaver', # Handle layered products
|
||||
'pkgset', # Define package sets
|
||||
'gather', # Download and organize packages
|
||||
'createrepo', # Create package repositories
|
||||
'buildinstall', # Build installation trees
|
||||
'extra_files', # Add additional files
|
||||
'createiso', # Create ISO images
|
||||
'extra_isos', # Generate additional ISO variants
|
||||
'image_build', # Build disk images via Koji
|
||||
'image_container', # Create container images
|
||||
'kiwibuild', # Build images via Kiwi
|
||||
'osbuild', # Build images via osbuild
|
||||
'imagebuilder', # Build images via imagebuilder
|
||||
'repoclosure', # Validate repository consistency
|
||||
'test', # Run tests
|
||||
'image_checksum', # Generate checksums
|
||||
'livemedia_phase', # Create live media
|
||||
'ostree', # Create OSTree commits
|
||||
'ostree_installer', # Create OSTree installers
|
||||
'ostree_container' # Create OSTree containers
|
||||
]
|
||||
```
|
||||
|
||||
### **Core Components**
|
||||
|
||||
#### **1. Compose Engine (`compose.py`)**
|
||||
The central orchestrator that manages the entire compose lifecycle:
|
||||
|
||||
```python
|
||||
class Compose(kobo.log.LoggingBase):
|
||||
def __init__(self, conf, topdir, skip_phases=None, just_phases=None, ...):
|
||||
self.conf = conf # Configuration
|
||||
self.variants = {} # Top-level variants
|
||||
self.all_variants = {} # All variants (including nested)
|
||||
self.paths = Paths(self) # Path management
|
||||
self.koji_downloader = KojiDownloadProxy.from_config(self.conf, self._logger)
|
||||
```
|
||||
|
||||
**Key Responsibilities**:
|
||||
- **Variant Management**: Handles complex variant hierarchies (layered products, nested variants)
|
||||
- **Path Coordination**: Manages thousands of paths across multiple architectures and variants
|
||||
- **Status Management**: Tracks compose status (STARTED → FINISHED/DOOMED/TERMINATED)
|
||||
- **Failure Tracking**: Maintains detailed logs of failed deliverables
|
||||
|
||||
#### **2. Phase System (`phases/`)**
|
||||
Each phase inherits from `PhaseBase` and implements a specific aspect of the compose:
|
||||
|
||||
```python
|
||||
class PhaseBase(object):
|
||||
def __init__(self, compose):
|
||||
self.compose = compose
|
||||
self.msg = "---------- PHASE: %s ----------" % self.name.upper()
|
||||
self.finished = False
|
||||
self._skipped = False
|
||||
|
||||
def skip(self):
|
||||
# Complex skip logic based on configuration and dependencies
|
||||
if self.name in self.compose.skip_phases:
|
||||
return True
|
||||
if self.name in self.compose.conf["skip_phases"]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def start(self):
|
||||
self._skipped = self.skip()
|
||||
if self._skipped:
|
||||
self.compose.log_warning("[SKIP ] %s" % self.msg)
|
||||
self.finished = True
|
||||
return
|
||||
self._start_time = time.time()
|
||||
self.compose.log_info("[BEGIN] %s" % self.msg)
|
||||
self.compose.notifier.send("phase-start", phase_name=self.name)
|
||||
self.run()
|
||||
```
|
||||
|
||||
#### **3. Wrapper System (`wrappers/`)**
|
||||
Pungi delegates actual work to external tools through wrapper classes:
|
||||
|
||||
- **`KojiWrapper`**: Manages Koji build system integration
|
||||
- **`CompsWrapper`**: Handles package group definitions
|
||||
- **`CreaterepoWrapper`**: Manages repository metadata creation
|
||||
- **`VariantsWrapper`**: Parses variant definitions
|
||||
|
||||
### **Data Flow Architecture**
|
||||
|
||||
#### **1. Koji-Pungi Data Flow**
|
||||
```python
|
||||
def download_packages_from_koji(self, package_list):
|
||||
"""Download packages from Koji build system"""
|
||||
koji_wrapper = KojiWrapper(self.compose)
|
||||
|
||||
for package in package_list:
|
||||
# Query Koji for package availability
|
||||
build_info = koji_wrapper.get_build_info(package)
|
||||
|
||||
if build_info['state'] != 'COMPLETE':
|
||||
raise PackageNotReadyError(f"Package {package} not ready in Koji")
|
||||
|
||||
# Download package from Koji
|
||||
koji_wrapper.download_rpm(build_info['rpm_id'], self.download_dir)
|
||||
```
|
||||
|
||||
#### **2. Pungi-Mock Data Flow**
|
||||
```python
|
||||
def execute_mock_build(self, build_spec):
|
||||
"""Execute build using Mock environment"""
|
||||
# Generate Mock configuration
|
||||
mock_config = self._create_mock_config(build_spec)
|
||||
|
||||
# Initialize Mock environment
|
||||
mock_init_cmd = ['mock', '--config', mock_config, '--init']
|
||||
subprocess.run(mock_init_cmd, check=True)
|
||||
|
||||
# Execute build in Mock environment
|
||||
mock_build_cmd = ['mock', '--config', mock_config, '--rebuild', build_spec['srpm']]
|
||||
result = subprocess.run(mock_build_cmd, capture_output=True)
|
||||
|
||||
return result
|
||||
```
|
||||
|
||||
#### **3. Configuration Loading**
|
||||
```python
|
||||
def get_compose_info(conf, compose_type="production", compose_date=None, ...):
|
||||
ci = ComposeInfo()
|
||||
ci.release.name = conf["release_name"]
|
||||
ci.release.short = conf["release_short"]
|
||||
ci.release.version = conf["release_version"]
|
||||
ci.release.is_layered = True if conf.get("base_product_name", "") else False
|
||||
# ... more configuration processing
|
||||
```
|
||||
|
||||
#### **2. Package Resolution & Download**
|
||||
The `gather` phase is particularly sophisticated and integrates with Koji:
|
||||
|
||||
```python
|
||||
class GatherPhase(PhaseBase):
|
||||
def __init__(self, compose, pkgset_phase):
|
||||
self.pkgset_phase = pkgset_phase
|
||||
self.manifest_file = self.compose.paths.compose.metadata("rpms.json")
|
||||
self.manifest = Rpms()
|
||||
# ... manifest setup
|
||||
|
||||
def run(self):
|
||||
# Query Koji for package availability
|
||||
self._check_koji_package_status()
|
||||
|
||||
# Download packages from Koji
|
||||
self._download_packages_from_koji()
|
||||
|
||||
# Complex package gathering logic with multiple sources
|
||||
# Handles dependencies, exclusions, multilib, etc.
|
||||
|
||||
def _check_koji_package_status(self):
|
||||
"""Ensure all required packages are available in Koji"""
|
||||
koji_wrapper = KojiWrapper(self.compose)
|
||||
for package in self.required_packages:
|
||||
if not koji_wrapper.is_package_available(package):
|
||||
raise PackageNotReadyError(f"Package {package} not ready in Koji")
|
||||
```
|
||||
|
||||
#### **3. OSTree Integration**
|
||||
Pungi's OSTree phases demonstrate its role as an orchestrator:
|
||||
|
||||
```python
|
||||
class OSTreePhase(ConfigGuardedPhase):
|
||||
def run(self):
|
||||
# Enqueue OSTree builds for each variant/architecture
|
||||
for variant in self.compose.get_variants():
|
||||
for conf in self.get_config_block(variant):
|
||||
for arch in conf.get("arches", []) or variant.arches:
|
||||
self._enqueue(variant, arch, conf)
|
||||
self.pool.start()
|
||||
```
|
||||
|
||||
#### **4. Mock Integration in Build Phases**
|
||||
Pungi can use Mock for specific build operations:
|
||||
|
||||
```python
|
||||
class MockBuildPhase(PhaseBase):
|
||||
def run(self):
|
||||
"""Execute builds using Mock environments"""
|
||||
for variant in self.compose.get_variants():
|
||||
for arch in variant.arches:
|
||||
# Create Mock environment for this variant/arch
|
||||
mock_env = self._create_mock_environment(variant, arch)
|
||||
|
||||
# Execute build in Mock environment
|
||||
result = self._execute_mock_build(mock_env, variant.build_spec)
|
||||
|
||||
# Collect results
|
||||
self._collect_build_results(result, variant, arch)
|
||||
|
||||
def _create_mock_environment(self, variant, arch):
|
||||
"""Create isolated build environment using Mock"""
|
||||
mock_config = self._generate_mock_config(variant, arch)
|
||||
mock_cmd = ['mock', '--config', mock_config, '--init']
|
||||
|
||||
subprocess.run(mock_cmd, check=True)
|
||||
return mock_config
|
||||
```
|
||||
|
||||
## Key Design Patterns & Philosophies
|
||||
|
||||
### **1. Orchestration Over Implementation**
|
||||
Pungi follows the **"orchestrator pattern"** - it coordinates rather than implements:
|
||||
|
||||
- **Package Building**: Delegates to Koji build system
|
||||
- **Image Creation**: Delegates to Kiwi, osbuild, imagebuilder
|
||||
- **OSTree Operations**: Delegates to rpm-ostree tools
|
||||
- **Repository Management**: Delegates to createrepo, dnf
|
||||
|
||||
### **2. Configuration-Driven Architecture**
|
||||
Everything in Pungi is driven by configuration:
|
||||
|
||||
```python
|
||||
def get_config_block(self, variant, arch=None):
|
||||
"""Find configuration block for given variant and arch"""
|
||||
if arch is not None:
|
||||
return util.get_arch_variant_data(
|
||||
self.compose.conf, self.name, arch, variant, keys=self.used_patterns
|
||||
)
|
||||
else:
|
||||
return util.get_variant_data(
|
||||
self.compose.conf, self.name, variant, keys=self.used_patterns
|
||||
)
|
||||
```
|
||||
|
||||
### **3. Variant-Centric Design**
|
||||
Pungi's architecture revolves around **variants** - different flavors of the same release:
|
||||
|
||||
- **Base Variants**: Core system variants (Server, Workstation, etc.)
|
||||
- **Layered Products**: Products built on top of base variants
|
||||
- **Nested Variants**: Sub-variants within main variants
|
||||
- **Architecture Variants**: Different CPU architectures
|
||||
|
||||
### **4. Failure Resilience**
|
||||
Pungi implements sophisticated failure handling:
|
||||
|
||||
```python
|
||||
def can_fail(self, variant, arch, deliverable):
|
||||
"""Figure out if deliverable can fail on variant.arch"""
|
||||
failable = get_arch_variant_data(
|
||||
self.compose.conf, "failable_deliverables", arch, variant
|
||||
)
|
||||
return deliverable in failable
|
||||
|
||||
def fail_deliverable(self, variant, arch, kind, subvariant=None):
|
||||
"""Log information about failed deliverable"""
|
||||
variant_uid = variant.uid if variant else ""
|
||||
self.failed_deliverables.setdefault(kind, []).append(
|
||||
(variant_uid, arch, subvariant)
|
||||
)
|
||||
```
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### **1. Multi-Architecture Support**
|
||||
Pungi handles complex multi-arch scenarios:
|
||||
|
||||
- **Primary Architectures**: x86_64, aarch64, ppc64le, s390x
|
||||
- **Architecture-Specific Variants**: Different package sets per architecture
|
||||
- **Cross-Architecture Dependencies**: Managing dependencies across architectures
|
||||
|
||||
### **2. Layered Product Support**
|
||||
Pungi can handle complex product layering:
|
||||
|
||||
```python
|
||||
def _prepare_variant_as_lookaside(compose):
|
||||
"""Handle variant dependencies for layered products"""
|
||||
variant_as_lookaside = compose.conf.get("variant_as_lookaside", [])
|
||||
graph = SimpleAcyclicOrientedGraph()
|
||||
for variant, lookaside_variant in variant_as_lookaside:
|
||||
graph.add_edge(variant, lookaside_variant)
|
||||
variant_processing_order = reversed(graph.prune_graph())
|
||||
return list(variant_processing_order)
|
||||
```
|
||||
|
||||
### **3. Parallel Execution**
|
||||
Pungi implements sophisticated parallelization:
|
||||
|
||||
```python
|
||||
def parallelBuild(treefile):
|
||||
workers = make(chan struct{}, config.MaxParallelBuilds)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for _, arch := range treefile.Architecture {
|
||||
wg.Add(1)
|
||||
go func(arch string) {
|
||||
defer wg.Done()
|
||||
workers <- struct{}{}
|
||||
defer func() { <-workers }()
|
||||
buildForArchitecture(treefile, arch)
|
||||
}(arch)
|
||||
}
|
||||
wg.Wait()
|
||||
```
|
||||
|
||||
### **4. Caching & Optimization**
|
||||
Pungi implements multiple caching layers:
|
||||
|
||||
- **Package Cache**: Reuses downloaded packages between builds
|
||||
- **Build Environment Cache**: Reuses build environments when possible
|
||||
- **Metadata Cache**: Caches repository metadata
|
||||
- **Dogpile Cache**: Distributed caching for large deployments
|
||||
|
||||
## Integration Points
|
||||
|
||||
### **The Pungi-Koji-Mock Workflow**
|
||||
|
||||
Pungi orchestrates a sophisticated workflow that integrates Koji and Mock at different stages:
|
||||
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Koji │ │ Pungi │ │ Mock │
|
||||
│ Build System │ │ Orchestrator │ │ Build Environment│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
│ 1. Build Packages │ │
|
||||
│──────────────────────▶│ │
|
||||
│ │ │
|
||||
│ 2. Package Available │ │
|
||||
│◀──────────────────────│ │
|
||||
│ │ │
|
||||
│ │ 3. Create Environment │
|
||||
│ │──────────────────────▶│
|
||||
│ │ │
|
||||
│ │ 4. Environment Ready │
|
||||
│ │◀──────────────────────│
|
||||
│ │ │
|
||||
│ │ 5. Execute Build │
|
||||
│ │──────────────────────▶│
|
||||
│ │ │
|
||||
│ │ 6. Build Complete │
|
||||
│ │◀──────────────────────│
|
||||
│ │ │
|
||||
│ 7. Compose Complete │ │
|
||||
│◀──────────────────────│ │
|
||||
```
|
||||
|
||||
**Workflow Stages**:
|
||||
1. **Koji Builds Packages**: Koji builds individual RPM packages in isolated environments
|
||||
2. **Pungi Coordinates**: Pungi waits for all required packages to be available in Koji
|
||||
3. **Mock Creates Environment**: Pungi uses Mock to create isolated build environments when needed
|
||||
4. **Build Execution**: Pungi executes build commands within Mock-managed environments
|
||||
5. **Result Collection**: Pungi collects build results and creates final compose artifacts
|
||||
|
||||
### **1. Koji Build System Integration**
|
||||
Pungi has deep integration with Fedora's Koji build system:
|
||||
|
||||
```python
|
||||
class KojiWrapper(object):
|
||||
def __init__(self, compose):
|
||||
self.profile = self.compose.conf["koji_profile"]
|
||||
self.koji_module = koji.get_profile_module(self.profile)
|
||||
self.koji_proxy = koji.ClientSession(self.koji_module.config.server, session_opts)
|
||||
|
||||
def download_rpms(self, rpms, dest_dir, arch=None):
|
||||
"""Download RPMs from Koji"""
|
||||
# Complex download logic with authentication and retry
|
||||
```
|
||||
|
||||
**How Pungi Uses Koji**:
|
||||
- **Package Source**: Pungi downloads pre-built RPM packages from Koji's build system
|
||||
- **Build Coordination**: Pungi coordinates with Koji to ensure package availability before compose
|
||||
- **Metadata Integration**: Pungi uses Koji's build metadata for package versioning and dependencies
|
||||
- **Build Status**: Pungi tracks Koji build status to ensure all required packages are available
|
||||
|
||||
### **2. Mock Build Environment Integration**
|
||||
Pungi can use Mock for creating isolated build environments when needed:
|
||||
|
||||
```python
|
||||
# Pungi can invoke Mock for creating chroot environments
|
||||
def create_build_environment(self, variant, arch):
|
||||
"""Create isolated build environment using Mock"""
|
||||
mock_config = self._generate_mock_config(variant, arch)
|
||||
mock_cmd = ['mock', '--config', mock_config, '--init']
|
||||
|
||||
# Execute Mock to create chroot
|
||||
result = subprocess.run(mock_cmd, capture_output=True)
|
||||
if result.returncode != 0:
|
||||
raise BuildError(f"Mock environment creation failed: {result.stderr}")
|
||||
|
||||
return mock_config
|
||||
```
|
||||
|
||||
**How Pungi Uses Mock**:
|
||||
- **Build Environment Creation**: Pungi can use Mock to create isolated chroot environments for specific builds
|
||||
- **Package Installation**: Pungi uses Mock's package management capabilities for installing build dependencies
|
||||
- **Environment Isolation**: Pungi leverages Mock's chroot isolation for reproducible builds
|
||||
- **Build Execution**: Pungi can execute build commands within Mock-managed environments
|
||||
|
||||
**Integration Mechanisms**:
|
||||
- **Command Invocation**: Pungi invokes Mock as a subprocess for environment management
|
||||
- **Configuration Sharing**: Pungi generates Mock configuration files based on compose requirements
|
||||
- **Result Collection**: Pungi collects build results from Mock-managed environments
|
||||
- **Cleanup Coordination**: Pungi coordinates cleanup of Mock environments after builds
|
||||
|
||||
### **3. OSTree/Bootc Integration**
|
||||
Pungi orchestrates bootc image creation:
|
||||
|
||||
```python
|
||||
class OSTreeContainerPhase(ConfigGuardedPhase):
|
||||
def worker(self, compose, variant, arch, config):
|
||||
# Clone configuration repository
|
||||
self._clone_repo(compose, repodir, config["config_url"], config.get("config_branch", "main"))
|
||||
|
||||
# Execute rpm-ostree container encapsulate
|
||||
# Generate container metadata
|
||||
# Handle signing and distribution
|
||||
```
|
||||
|
||||
### **4. Repository Management**
|
||||
Coordinates with multiple repository types:
|
||||
|
||||
- **Package Repositories**: RPM repositories with metadata
|
||||
- **Module Repositories**: Modularity metadata
|
||||
- **Comps Repositories**: Package group definitions
|
||||
- **Lookaside Repositories**: Additional package sources
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
### **1. Scalability**
|
||||
Pungi is designed for large-scale operations:
|
||||
|
||||
- **Parallel Builds**: Supports hundreds of concurrent builds
|
||||
- **Distributed Execution**: Can distribute work across multiple hosts
|
||||
- **Resource Management**: Implements sophisticated resource controls
|
||||
- **Caching**: Multiple layers of caching for performance
|
||||
|
||||
### **2. Resource Usage**
|
||||
Pungi manages resources carefully:
|
||||
|
||||
- **Memory Management**: Controlled memory usage during builds
|
||||
- **Disk Space**: Monitors and manages disk space usage
|
||||
- **Network Throttling**: Controls bandwidth for package downloads
|
||||
- **CPU Limits**: Manages CPU usage for parallel operations
|
||||
|
||||
### **3. Monitoring & Observability**
|
||||
Comprehensive monitoring capabilities:
|
||||
|
||||
```python
|
||||
def write_status(self, stat_msg):
|
||||
"""Write compose status with comprehensive logging"""
|
||||
if stat_msg not in ("STARTED", "FINISHED", "DOOMED", "TERMINATED"):
|
||||
self.log_warning("Writing nonstandard compose status: %s" % stat_msg)
|
||||
|
||||
if stat_msg == "FINISHED" and self.failed_deliverables:
|
||||
stat_msg = "FINISHED_INCOMPLETE"
|
||||
|
||||
self._log_failed_deliverables()
|
||||
# ... status writing and notification
|
||||
```
|
||||
|
||||
## Comparison with deb-compose Vision
|
||||
|
||||
### **Similarities**
|
||||
- **Phase-based architecture**: Both use ordered phases for orchestration
|
||||
- **Configuration-driven**: Both rely heavily on configuration files
|
||||
- **Multi-artifact output**: Both generate multiple output formats
|
||||
- **OSTree integration**: Both integrate with OSTree for bootc images
|
||||
|
||||
### **Key Differences**
|
||||
- **Package Management**: Pungi uses RPM/Koji, deb-compose uses DEB/sbuild
|
||||
- **Build System**: Pungi delegates to Koji, deb-compose manages sbuild directly
|
||||
- **Complexity**: Pungi is more mature with 20+ phases, deb-compose is simpler
|
||||
- **Integration**: Pungi has deeper integration with Fedora infrastructure
|
||||
|
||||
## Lessons for deb-compose
|
||||
|
||||
### **1. Architecture Strengths to Emulate**
|
||||
- **Phase-based orchestration**: Clear separation of concerns
|
||||
- **Failure resilience**: Sophisticated error handling and recovery
|
||||
- **Configuration flexibility**: Rich configuration system
|
||||
- **Parallel execution**: Efficient resource utilization
|
||||
|
||||
### **2. Complexity to Avoid Initially**
|
||||
- **Layered products**: Start with simple variants
|
||||
- **Complex dependency graphs**: Begin with linear phase dependencies
|
||||
- **Multiple build backends**: Focus on one build system initially
|
||||
- **Advanced caching**: Implement basic caching first
|
||||
|
||||
### **3. Implementation Priorities**
|
||||
- **Core orchestration**: Focus on phase management
|
||||
- **Basic OSTree integration**: Simple bootc image creation
|
||||
- **Error handling**: Basic failure recovery
|
||||
- **Configuration system**: Simple but flexible configuration
|
||||
|
||||
## Technical Implementation Details
|
||||
|
||||
### **Entry Point Architecture**
|
||||
Pungi's main entry point (`pungi_koji.py`) demonstrates its orchestration approach:
|
||||
|
||||
```python
|
||||
def main():
|
||||
parser = argparse.ArgumentParser()
|
||||
# ... argument parsing
|
||||
|
||||
# Load configuration and create compose
|
||||
conf = kobo.conf.PyConfigParser()
|
||||
conf.load_from_file(args.config)
|
||||
|
||||
# Create compose directory and initialize
|
||||
compose_dir = get_compose_dir(args.target_dir, conf, ...)
|
||||
|
||||
# Execute phases in order
|
||||
for phase_name in PHASES_NAMES:
|
||||
if phase_name in args.skip_phase:
|
||||
continue
|
||||
phase = get_phase(phase_name, compose)
|
||||
phase.start()
|
||||
```
|
||||
|
||||
### **Path Management System**
|
||||
Pungi's path management is incredibly sophisticated:
|
||||
|
||||
```python
|
||||
class Paths(object):
|
||||
def __init__(self, compose):
|
||||
self.compose = compose
|
||||
self.topdir = compose.topdir
|
||||
|
||||
def work(self, arch=None, variant=None):
|
||||
"""Get work directory paths"""
|
||||
if arch == "global":
|
||||
return os.path.join(self.topdir, "work", "global")
|
||||
elif variant:
|
||||
return os.path.join(self.topdir, "work", arch, variant.uid)
|
||||
else:
|
||||
return os.path.join(self.topdir, "work", arch)
|
||||
```
|
||||
|
||||
### **Error Handling Patterns**
|
||||
Pungi implements sophisticated error handling:
|
||||
|
||||
```python
|
||||
def failable(compose, can_fail, variant, arch, deliverable):
|
||||
"""Context manager for failable deliverables"""
|
||||
try:
|
||||
yield
|
||||
except Exception as e:
|
||||
if can_fail:
|
||||
compose.fail_deliverable(variant, arch, deliverable)
|
||||
compose.log_warning("Failed %s on %s/%s: %s" % (deliverable, variant, arch, e))
|
||||
else:
|
||||
raise
|
||||
```
|
||||
|
||||
## Production Readiness Features
|
||||
|
||||
### **1. Authentication & Security**
|
||||
- **Kerberos Integration**: Enterprise-grade authentication
|
||||
- **OIDC Support**: Modern identity provider integration
|
||||
- **Certificate Management**: SSL/TLS certificate handling
|
||||
- **Access Control**: Granular permissions per variant/architecture
|
||||
|
||||
### **2. Monitoring & Alerting**
|
||||
- **Status Tracking**: Real-time compose status monitoring
|
||||
- **Progress Reporting**: Detailed progress through phases
|
||||
- **Failure Notification**: Immediate alerts on failures
|
||||
- **Metrics Collection**: Performance and resource usage metrics
|
||||
|
||||
### **3. Recovery & Resilience**
|
||||
- **Partial Success Handling**: Continues with successful variants
|
||||
- **Retry Mechanisms**: Automatic retry for transient failures
|
||||
- **State Persistence**: Maintains state across restarts
|
||||
- **Cleanup Procedures**: Automatic cleanup of failed builds
|
||||
|
||||
## Conclusion
|
||||
|
||||
Pungi represents a **mature, production-grade orchestration system** that has evolved over years to handle Fedora's complex release process. Its key insight is that **orchestration is more valuable than implementation** - by coordinating existing tools rather than rebuilding functionality, it achieves reliability and maintainability.
|
||||
|
||||
### **The Complete Integration Picture**
|
||||
|
||||
Pungi's success comes from its ability to orchestrate three complementary systems:
|
||||
|
||||
1. **Koji**: Provides the **package foundation** - building individual RPM packages in isolated environments
|
||||
2. **Mock**: Provides the **build environment** - creating isolated chroots for specific build operations
|
||||
3. **Pungi**: Provides the **orchestration layer** - coordinating the entire compose process
|
||||
|
||||
**Why This Architecture Works**:
|
||||
- **Separation of Concerns**: Each system has a focused responsibility
|
||||
- **Leverage Existing Tools**: Pungi doesn't rebuild what Koji and Mock already do well
|
||||
- **Flexible Integration**: Pungi can use Mock when needed, but doesn't require it for all operations
|
||||
- **Scalable Coordination**: Pungi can coordinate complex workflows across multiple systems
|
||||
|
||||
**The Orchestration Advantage**:
|
||||
- **Koji handles package building** at scale across multiple architectures
|
||||
- **Mock handles environment isolation** when specific build environments are needed
|
||||
- **Pungi handles release coordination** ensuring all pieces fit together correctly
|
||||
|
||||
This architecture allows Fedora to maintain massive scale while keeping individual components focused and maintainable.
|
||||
|
||||
For deb-compose, the lesson is clear: **focus on being an excellent orchestrator** rather than trying to implement everything. Pungi's success comes from its ability to coordinate complex workflows while delegating actual work to specialized tools. This architecture allows it to handle Fedora's massive scale while remaining maintainable and extensible.
|
||||
|
||||
The roadmap's approach of building incrementally with clear phases aligns well with Pungi's proven architecture. By starting with core orchestration and gradually adding complexity, deb-compose can achieve similar reliability without the initial complexity that Pungi has accumulated over years of production use.
|
||||
|
||||
### **Key Takeaways for deb-compose Development**
|
||||
|
||||
1. **Start Simple**: Begin with basic phase orchestration rather than complex features
|
||||
2. **Delegate Wisely**: Focus on coordination, not implementation
|
||||
3. **Fail Gracefully**: Implement basic error handling from the start
|
||||
4. **Grow Incrementally**: Add complexity only when needed
|
||||
5. **Learn from Pungi**: Study Pungi's patterns but avoid its complexity initially
|
||||
|
||||
This analysis provides a solid foundation for understanding how to build a successful compose orchestration system while avoiding the pitfalls of over-engineering early in development.
|
||||
Loading…
Add table
Add a link
Reference in a new issue