deb-bootc-image-builder-new/bib/internal/config/config.go
2025-09-05 07:10:12 -07:00

296 lines
8.8 KiB
Go

package config
import (
"fmt"
"os"
"path/filepath"
"strings"
"gopkg.in/yaml.v3"
)
// RegistryConfig represents the configuration for a container registry
type RegistryConfig struct {
BaseURL string `yaml:"base_url"`
Namespace string `yaml:"namespace"`
AuthRequired bool `yaml:"auth_required"`
Description string `yaml:"description"`
}
// ContainerTemplates defines naming templates for containers
type ContainerTemplates struct {
BootcBase string `yaml:"bootc_base"`
BootcBuilder string `yaml:"bootc_builder"`
}
// VersionMappings defines version mappings for different distributions
type VersionMappings struct {
Debian map[string]string `yaml:"debian"`
}
// DefaultSettings contains default configuration values
type DefaultSettings struct {
DebianVersion string `yaml:"debian_version"`
ImageTypes []string `yaml:"image_types"`
OutputDir string `yaml:"output_dir"`
RootfsType string `yaml:"rootfs_type"`
Architecture string `yaml:"architecture"`
}
// BuildSettings contains build-specific configuration
type BuildSettings struct {
ContainerSizeMultiplier int `yaml:"container_size_multiplier"`
MinRootfsSizeGB int `yaml:"min_rootfs_size_gb"`
DefaultKernelOptions []string `yaml:"default_kernel_options"`
ExperimentalFeatures map[string]bool `yaml:"experimental_features"`
}
// RepositoryConfig defines APT repository configuration
type RepositoryConfig struct {
Debian map[string]string `yaml:"debian"`
DebianForge struct {
BaseURL string `yaml:"base_url"`
Components []string `yaml:"components"`
} `yaml:"debian_forge"`
Priorities map[string]int `yaml:"priorities"`
}
// CloudConfig contains cloud upload settings
type CloudConfig struct {
AWS struct {
DefaultRegion string `yaml:"default_region"`
BucketTemplate string `yaml:"bucket_template"`
} `yaml:"aws"`
}
// LoggingConfig defines logging configuration
type LoggingConfig struct {
Level string `yaml:"level"`
Format string `yaml:"format"`
Verbose bool `yaml:"verbose"`
}
// SecurityConfig defines security settings
type SecurityConfig struct {
RequireHTTPS bool `yaml:"require_https"`
VerifyTLS bool `yaml:"verify_tls"`
AllowInsecure bool `yaml:"allow_insecure"`
}
// Config represents the complete configuration structure
type Config struct {
Registries map[string]RegistryConfig `yaml:"registries"`
ActiveRegistry string `yaml:"active_registry"`
Containers ContainerTemplates `yaml:"containers"`
Versions VersionMappings `yaml:"versions"`
Defaults DefaultSettings `yaml:"defaults"`
Build BuildSettings `yaml:"build"`
Repositories RepositoryConfig `yaml:"repositories"`
Cloud CloudConfig `yaml:"cloud"`
Logging LoggingConfig `yaml:"logging"`
Security SecurityConfig `yaml:"security"`
}
// LoadConfig loads configuration from the specified file path
func LoadConfig(configPath string) (*Config, error) {
if configPath == "" {
// Try to find config in standard locations
configPath = findConfigFile()
}
if configPath == "" {
return nil, fmt.Errorf("no configuration file found")
}
data, err := os.ReadFile(configPath)
if err != nil {
return nil, fmt.Errorf("failed to read config file %s: %w", configPath, err)
}
var config Config
if err := yaml.Unmarshal(data, &config); err != nil {
return nil, fmt.Errorf("failed to parse config file %s: %w", configPath, err)
}
// Validate configuration
if err := config.Validate(); err != nil {
return nil, fmt.Errorf("invalid configuration: %w", err)
}
return &config, nil
}
// findConfigFile searches for configuration file in standard locations
func findConfigFile() string {
// Search paths in order of preference
searchPaths := []string{
"./.config/registry.yaml",
"./registry.yaml",
"~/.config/debian-bootc-image-builder/registry.yaml",
"/etc/debian-bootc-image-builder/registry.yaml",
}
for _, path := range searchPaths {
if strings.HasPrefix(path, "~/") {
homeDir, err := os.UserHomeDir()
if err != nil {
continue
}
path = filepath.Join(homeDir, path[2:])
}
if _, err := os.Stat(path); err == nil {
return path
}
}
return ""
}
// Validate checks if the configuration is valid
func (c *Config) Validate() error {
// Check if active registry exists
if c.ActiveRegistry == "" {
return fmt.Errorf("active_registry is required")
}
if _, exists := c.Registries[c.ActiveRegistry]; !exists {
return fmt.Errorf("active registry '%s' not found in registries", c.ActiveRegistry)
}
// Validate registry configurations
for name, registry := range c.Registries {
if registry.BaseURL == "" {
return fmt.Errorf("registry '%s' missing base_url", name)
}
if registry.Namespace == "" {
return fmt.Errorf("registry '%s' missing namespace", name)
}
}
// Validate container templates
if c.Containers.BootcBase == "" {
return fmt.Errorf("bootc_base container template is required")
}
if c.Containers.BootcBuilder == "" {
return fmt.Errorf("bootc_builder container template is required")
}
// Validate version mappings
if len(c.Versions.Debian) == 0 {
return fmt.Errorf("debian version mappings are required")
}
return nil
}
// GetActiveRegistry returns the currently active registry configuration
func (c *Config) GetActiveRegistry() (*RegistryConfig, error) {
registry, exists := c.Registries[c.ActiveRegistry]
if !exists {
return nil, fmt.Errorf("active registry '%s' not found", c.ActiveRegistry)
}
return &registry, nil
}
// GetContainerName generates a container name using the specified template
func (c *Config) GetContainerName(template string, variables map[string]string) (string, error) {
registry, err := c.GetActiveRegistry()
if err != nil {
return "", err
}
// Add default variables
if variables == nil {
variables = make(map[string]string)
}
variables["registry"] = registry.BaseURL
variables["namespace"] = registry.Namespace
// Replace variables in template
result := template
for key, value := range variables {
placeholder := "{" + key + "}"
result = strings.ReplaceAll(result, placeholder, value)
}
// Check for unresolved variables
if strings.Contains(result, "{") {
return "", fmt.Errorf("unresolved variables in template: %s", result)
}
return result, nil
}
// GetBootcBaseName generates the bootc base container name
func (c *Config) GetBootcBaseName(version string) (string, error) {
variables := map[string]string{
"version": version,
}
return c.GetContainerName(c.Containers.BootcBase, variables)
}
// GetBootcBuilderName generates the bootc builder container name
func (c *Config) GetBootcBuilderName(tag string) (string, error) {
variables := map[string]string{
"tag": tag,
}
return c.GetContainerName(c.Containers.BootcBuilder, variables)
}
// GetDebianVersion returns the actual Debian version for a given version name
func (c *Config) GetDebianVersion(versionName string) (string, error) {
if version, exists := c.Versions.Debian[versionName]; exists {
return version, nil
}
return "", fmt.Errorf("unknown Debian version: %s", versionName)
}
// GetDefaultDebianVersion returns the default Debian version
func (c *Config) GetDefaultDebianVersion() (string, error) {
return c.GetDebianVersion(c.Defaults.DebianVersion)
}
// IsExperimentalFeatureEnabled checks if an experimental feature is enabled
func (c *Config) IsExperimentalFeatureEnabled(feature string) bool {
if enabled, exists := c.Build.ExperimentalFeatures[feature]; exists {
return enabled
}
return false
}
// GetRepositoryURL returns the URL for a specific repository
func (c *Config) GetRepositoryURL(repoName string) (string, error) {
if url, exists := c.Repositories.Debian[repoName]; exists {
return url, nil
}
return "", fmt.Errorf("unknown repository: %s", repoName)
}
// GetRepositoryPriority returns the priority for a specific repository
func (c *Config) GetRepositoryPriority(repoName string) int {
if priority, exists := c.Repositories.Priorities[repoName]; exists {
return priority
}
return 500 // default priority
}
// GetDebianForgeRepository returns the debian-forge repository configuration
func (c *Config) GetDebianForgeRepository() (string, []string) {
return c.Repositories.DebianForge.BaseURL, c.Repositories.DebianForge.Components
}
// GetDefaultKernelOptions returns the default kernel options
func (c *Config) GetDefaultKernelOptions() []string {
return c.Build.DefaultKernelOptions
}
// GetContainerSizeMultiplier returns the container size multiplier
func (c *Config) GetContainerSizeMultiplier() int {
return c.Build.ContainerSizeMultiplier
}
// GetMinRootfsSizeGB returns the minimum root filesystem size in GB
func (c *Config) GetMinRootfsSizeGB() int {
return c.Build.MinRootfsSizeGB
}