go.mod: update osbuild/images to v0.123.0

Includes modularity support.
This commit is contained in:
Sanne Raymaekers 2025-03-10 11:29:18 +01:00 committed by Tomáš Hozza
parent 5e3d6aff54
commit 536b7d95c5
37 changed files with 655 additions and 157 deletions

View file

@ -3,7 +3,9 @@ package manifest
import (
"fmt"
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/experimentalflags"
"github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/rpmmd"
"github.com/osbuild/images/pkg/runner"
@ -57,6 +59,11 @@ func NewBuild(m *Manifest, runner runner.Runner, repos []rpmmd.RepoConfig, opts
repos: filterRepos(repos, name),
containerBuildable: opts.ContainerBuildable,
}
// This allows to bootstrap the buildroot with a custom container
// for e.g. cross-arch-build experiments,
maybeAddExperimentalContainerBootstrap(m, runner, opts, pipeline)
m.addPipeline(pipeline)
return pipeline
}
@ -149,6 +156,40 @@ func (p *BuildrootFromPackages) getSELinuxLabels() map[string]string {
return labels
}
// maybeAddExperimentalContainerBootstrap will return a container buildroot
// if the "IMAGE_BUILDER_EXPERIMENTAL=bootstrap=<container-ref>" is
// defined. This allows us to do cross-arch build experimentation.
//
// A "bootstrap" container has only these requirements:
// - python3 for the runners
// - rpm so that the real buildroot rpms can get installed
// - setfiles so that the selinux stage for the real buildroot can run
// (and does not even need a working dnf or repo setup).
func maybeAddExperimentalContainerBootstrap(m *Manifest, runner runner.Runner, opts *BuildOptions, build *BuildrootFromPackages) {
bootstrapBuildrootRef := experimentalflags.String("bootstrap")
if bootstrapBuildrootRef == "" {
return
}
cntSrcs := []container.SourceSpec{
{
Source: bootstrapBuildrootRef,
Name: bootstrapBuildrootRef,
TLSVerify: common.ToPtr(false),
},
}
name := "bootstrap-buildroot"
bootstrapPipeline := &BuildrootFromContainer{
Base: NewBase(name, nil),
runner: runner,
dependents: make([]Pipeline, 0),
containers: cntSrcs,
disableSelinux: true,
}
m.addPipeline(bootstrapPipeline)
build.build = bootstrapPipeline
}
type BuildrootFromContainer struct {
Base
@ -159,6 +200,7 @@ type BuildrootFromContainer struct {
containerSpecs []container.Spec
containerBuildable bool
disableSelinux bool
}
// NewBuildFromContainer creates a new build pipeline from the given
@ -213,6 +255,10 @@ func (p *BuildrootFromContainer) serializeEnd() {
}
func (p *BuildrootFromContainer) getSELinuxLabels() map[string]string {
if p.disableSelinux {
return nil
}
labels := map[string]string{
"/usr/bin/ostree": "system_u:object_r:install_exec_t:s0",
}
@ -242,13 +288,15 @@ func (p *BuildrootFromContainer) serialize() osbuild.Pipeline {
panic(err)
}
pipeline.AddStage(stage)
pipeline.AddStage(osbuild.NewSELinuxStage(
&osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
ExcludePaths: []string{"/sysroot"},
Labels: p.getSELinuxLabels(),
},
))
if !p.disableSelinux {
pipeline.AddStage(osbuild.NewSELinuxStage(
&osbuild.SELinuxStageOptions{
FileContexts: "etc/selinux/targeted/contexts/files/file_contexts",
ExcludePaths: []string{"/sysroot"},
Labels: p.getSELinuxLabels(),
},
))
}
return pipeline
}

View file

@ -22,15 +22,6 @@ import (
"github.com/osbuild/images/pkg/rpmmd"
)
type Arch uint64
const (
ARCH_X86_64 Arch = iota
ARCH_AARCH64
ARCH_S390X
ARCH_PPC64LE
)
type Distro uint64
const (

View file

@ -149,10 +149,14 @@ type OSCustomizations struct {
// instead of BLS. Required for legacy systems like RHEL 7.
NoBLS bool
// FirstBoot sets if the machine-id should be written with the
// magic value that determines if the machine is being booted for the
// first time.
FirstBoot bool
// InstallWeakDeps enables installation of weak dependencies for packages
// that are statically defined for the pipeline.
// Defaults to True.
InstallWeakDeps bool
// Determines if the machine id should be set to "uninitialized" which allows
// "ConditionFirstBoot" to work in systemd
MachineIdUninitialized bool
}
// OS represents the filesystem tree of the target image. This roughly
@ -184,6 +188,7 @@ type OS struct {
// content-related fields
repos []rpmmd.RepoConfig
packageSpecs []rpmmd.PackageSpec
moduleSpecs []rpmmd.ModuleSpec
containerSpecs []container.Spec
ostreeParentSpec *ostree.CommitSpec
@ -193,11 +198,6 @@ type OS struct {
OSProduct string
OSVersion string
OSNick string
// InstallWeakDeps enables installation of weak dependencies for packages
// that are statically defined for the pipeline.
// Defaults to True.
InstallWeakDeps bool
}
// NewOS creates a new OS pipeline. build is the build pipeline to use for
@ -206,10 +206,9 @@ type OS struct {
func NewOS(buildPipeline Build, platform platform.Platform, repos []rpmmd.RepoConfig) *OS {
name := "os"
p := &OS{
Base: NewBase(name, buildPipeline),
repos: filterRepos(repos, name),
platform: platform,
InstallWeakDeps: true,
Base: NewBase(name, buildPipeline),
repos: filterRepos(repos, name),
platform: platform,
}
buildPipeline.addDependent(p)
return p
@ -281,10 +280,17 @@ func (p *OS) getPackageSetChain(Distro) []rpmmd.PackageSet {
if p.Workload != nil {
workloadPackages := p.Workload.GetPackages()
if len(workloadPackages) > 0 {
chain = append(chain, rpmmd.PackageSet{
ps := rpmmd.PackageSet{
Include: workloadPackages,
Repositories: append(osRepos, p.Workload.GetRepos()...),
})
}
workloadModules := p.Workload.GetEnabledModules()
if len(workloadModules) > 0 {
ps.EnabledModules = workloadModules
}
chain = append(chain, ps)
}
}
@ -387,6 +393,7 @@ func (p *OS) serializeStart(inputs Inputs) {
}
p.packageSpecs = inputs.Depsolved.Packages
p.moduleSpecs = inputs.Depsolved.Modules
p.containerSpecs = inputs.Containers
if len(inputs.Commits) > 0 {
if len(inputs.Commits) > 1 {
@ -742,6 +749,36 @@ func (p *OS) serialize() osbuild.Pipeline {
pipeline.AddStages(osbuild.GenFileNodesStages(p.Files)...)
}
// write modularity related configuration files
if len(p.moduleSpecs) > 0 {
pipeline.AddStages(osbuild.GenDNFModuleConfigStages(p.moduleSpecs)...)
var failsafeFiles []*fsnode.File
// the failsafe file is a blob of YAML returned directly from the depsolver,
// we write them as 'normal files' without a special stage
for _, module := range p.moduleSpecs {
moduleFailsafeFile, err := fsnode.NewFile(module.FailsafeFile.Path, nil, nil, nil, []byte(module.FailsafeFile.Data))
if err != nil {
panic("failed to create module failsafe file")
}
failsafeFiles = append(failsafeFiles, moduleFailsafeFile)
}
failsafeDir, err := fsnode.NewDirectory("/var/lib/dnf/modulefailsafe", nil, nil, nil, true)
if err != nil {
panic("failed to create module failsafe directory")
}
pipeline.AddStages(osbuild.GenDirectoryNodesStages([]*fsnode.Directory{failsafeDir})...)
pipeline.AddStages(osbuild.GenFileNodesStages(failsafeFiles)...)
p.Files = append(p.Files, failsafeFiles...)
}
enabledServices := []string{}
disabledServices := []string{}
maskedServices := []string{}
@ -813,7 +850,7 @@ func (p *OS) serialize() osbuild.Pipeline {
pipeline.AddStage(osbuild.NewCAStageStage())
}
if p.FirstBoot {
if p.MachineIdUninitialized {
pipeline.AddStage(osbuild.NewMachineIdStage(&osbuild.MachineIdStageOptions{
FirstBoot: osbuild.MachineIdFirstBootYes,
}))

View file

@ -210,11 +210,22 @@ func (p *RawBootcImage) serialize() osbuild.Pipeline {
// First create custom directories, because some of the custom files may depend on them
if len(p.Directories) > 0 {
pipeline.AddStages(osbuild.GenDirectoryNodesStages(p.Directories)...)
stages := osbuild.GenDirectoryNodesStages(p.Directories)
for _, stage := range stages {
stage.Mounts = mounts
stage.Devices = devices
}
pipeline.AddStages(stages...)
}
if len(p.Files) > 0 {
pipeline.AddStages(osbuild.GenFileNodesStages(p.Files)...)
stages := osbuild.GenFileNodesStages(p.Files)
for _, stage := range stages {
stage.Mounts = mounts
stage.Devices = devices
}
pipeline.AddStages(stages...)
}
// XXX: maybe go back to adding this conditionally when we stop