go.mod: update to latest images@v0.111.0

This commit is contained in:
Michael Vogt 2025-01-20 12:47:16 +01:00 committed by Tomáš Hozza
parent 40011e35a2
commit 0d669dddbf
39 changed files with 521 additions and 169 deletions

2
go.mod
View file

@ -46,7 +46,7 @@ require (
github.com/labstack/gommon v0.4.2 github.com/labstack/gommon v0.4.2
github.com/openshift-online/ocm-sdk-go v0.1.438 github.com/openshift-online/ocm-sdk-go v0.1.438
github.com/oracle/oci-go-sdk/v54 v54.0.0 github.com/oracle/oci-go-sdk/v54 v54.0.0
github.com/osbuild/images v0.109.0 github.com/osbuild/images v0.111.0
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d
github.com/osbuild/pulp-client v0.1.0 github.com/osbuild/pulp-client v0.1.0
github.com/prometheus/client_golang v1.20.2 github.com/prometheus/client_golang v1.20.2

4
go.sum
View file

@ -541,8 +541,8 @@ github.com/openshift-online/ocm-sdk-go v0.1.438 h1:tsLCCUzbLCTL4RZG02y9RuopmGCXp
github.com/openshift-online/ocm-sdk-go v0.1.438/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y= github.com/openshift-online/ocm-sdk-go v0.1.438/go.mod h1:CiAu2jwl3ITKOxkeV0Qnhzv4gs35AmpIzVABQLtcI2Y=
github.com/oracle/oci-go-sdk/v54 v54.0.0 h1:CDLjeSejv2aDpElAJrhKpi6zvT/zhZCZuXchUUZ+LS4= github.com/oracle/oci-go-sdk/v54 v54.0.0 h1:CDLjeSejv2aDpElAJrhKpi6zvT/zhZCZuXchUUZ+LS4=
github.com/oracle/oci-go-sdk/v54 v54.0.0/go.mod h1:+t+yvcFGVp+3ZnztnyxqXfQDsMlq8U25faBLa+mqCMc= github.com/oracle/oci-go-sdk/v54 v54.0.0/go.mod h1:+t+yvcFGVp+3ZnztnyxqXfQDsMlq8U25faBLa+mqCMc=
github.com/osbuild/images v0.109.0 h1:yLY1Ul6O/4fp+y+UI2XIML9CcsKdPNTARk95hiz1syY= github.com/osbuild/images v0.111.0 h1:mnPLdSin/q1ZTaGZVJHepsikguFjUMAWblQdPgvZ02M=
github.com/osbuild/images v0.109.0/go.mod h1:58tzp7jV50rjaH9gMpvmQdVati0c4TaC5Op7wmSD/tY= github.com/osbuild/images v0.111.0/go.mod h1:58tzp7jV50rjaH9gMpvmQdVati0c4TaC5Op7wmSD/tY=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d h1:r9BFPDv0uuA9k1947Jybcxs36c/pTywWS1gjeizvtcQ= github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d h1:r9BFPDv0uuA9k1947Jybcxs36c/pTywWS1gjeizvtcQ=
github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d/go.mod h1:zR1iu/hOuf+OQNJlk70tju9IqzzM4ycq0ectkFBm94U= github.com/osbuild/osbuild-composer/pkg/splunk_logger v0.0.0-20240814102216-0239db53236d/go.mod h1:zR1iu/hOuf+OQNJlk70tju9IqzzM4ycq0ectkFBm94U=
github.com/osbuild/pulp-client v0.1.0 h1:L0C4ezBJGTamN3BKdv+rKLuq/WxXJbsFwz/Hj7aEmJ8= github.com/osbuild/pulp-client v0.1.0 h1:L0C4ezBJGTamN3BKdv+rKLuq/WxXJbsFwz/Hj7aEmJ8=

View file

@ -18,6 +18,7 @@ func CryptSHA512(phrase string) (string, error) {
return "", nil return "", nil
} }
// Note: update "crypt_impl_non_cgo.go" if new hash types get added
hashSettings := "$6$" + salt hashSettings := "$6$" + salt
return crypt(phrase, hashSettings) return crypt(phrase, hashSettings)
} }

View file

@ -0,0 +1,34 @@
//go:build !cgo
//
// fallback implementation of "crypt" for cross building
package crypt
import (
"bytes"
"fmt"
"os/exec"
"strings"
)
func crypt(pass, salt string) (string, error) {
// we could extract the "hash-type" here and pass it to
// openssl instead of hardcoding -6 but lets do that once we
// actually move away from sha512crypt
if !strings.HasPrefix(salt, "$6$") {
return "", fmt.Errorf("only crypt type SHA512 supported, got %q", salt)
}
cmd := exec.Command(
"openssl", "passwd", "-6",
// strip the $6$
"-salt", salt[3:],
"-stdin",
)
cmd.Stdin = bytes.NewBufferString(pass)
output, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("cannot generate password: %v, output:%s\n", err, string(output))
}
return strings.TrimSpace(string(output)), nil
}

View file

@ -93,6 +93,9 @@ var (
osPkgsKey: minimalrpmPackageSet, osPkgsKey: minimalrpmPackageSet,
installerPkgsKey: imageInstallerPackageSet, installerPkgsKey: imageInstallerPackageSet,
}, },
defaultImageConfig: &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
},
bootable: true, bootable: true,
bootISO: true, bootISO: true,
rpmOstree: false, rpmOstree: false,
@ -113,6 +116,9 @@ var (
packageSets: map[string]packageSetFunc{ packageSets: map[string]packageSetFunc{
installerPkgsKey: liveInstallerPackageSet, installerPkgsKey: liveInstallerPackageSet,
}, },
defaultImageConfig: &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
},
bootable: true, bootable: true,
bootISO: true, bootISO: true,
rpmOstree: false, rpmOstree: false,

View file

@ -407,6 +407,10 @@ func liveInstallerImage(workload workload.Workload,
img.RootfsType = manifest.SquashfsRootfs img.RootfsType = manifest.SquashfsRootfs
} }
if locale := t.getDefaultImageConfig().Locale; locale != nil {
img.Locale = *locale
}
return img, nil return img, nil
} }
@ -423,6 +427,11 @@ func imageInstallerImage(workload workload.Workload,
img := image.NewAnacondaTarInstaller() img := image.NewAnacondaTarInstaller()
var err error var err error
img.OSCustomizations, err = osCustomizations(t, packageSets[osPkgsKey], containers, bp.Customizations)
if err != nil {
return nil, err
}
img.Kickstart, err = kickstart.New(customizations) img.Kickstart, err = kickstart.New(customizations)
if err != nil { if err != nil {
return nil, err return nil, err
@ -453,11 +462,6 @@ func imageInstallerImage(workload workload.Workload,
img.Platform = t.platform img.Platform = t.platform
img.Workload = workload img.Workload = workload
img.OSCustomizations, err = osCustomizations(t, packageSets[osPkgsKey], containers, bp.Customizations)
if err != nil {
return nil, err
}
img.ExtraBasePackages = packageSets[installerPkgsKey] img.ExtraBasePackages = packageSets[installerPkgsKey]
d := t.arch.distro d := t.arch.distro
@ -479,7 +483,7 @@ func imageInstallerImage(workload workload.Workload,
img.Filename = t.Filename() img.Filename = t.Filename()
img.SquashfsCompression = "lz4" img.RootfsCompression = "lz4"
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) { if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs img.RootfsType = manifest.SquashfsRootfs
} }
@ -680,11 +684,15 @@ func iotInstallerImage(workload workload.Workload,
img.Filename = t.Filename() img.Filename = t.Filename()
img.SquashfsCompression = "lz4" img.RootfsCompression = "lz4"
if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) { if common.VersionGreaterThanOrEqual(img.OSVersion, VERSION_ROOTFS_SQUASHFS) {
img.RootfsType = manifest.SquashfsRootfs img.RootfsType = manifest.SquashfsRootfs
} }
if locale := t.getDefaultImageConfig().Locale; locale != nil {
img.Locale = *locale
}
return img, nil return img, nil
} }

View file

@ -97,7 +97,6 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
"cryptsetup", "cryptsetup",
"curl", "curl",
"dbus-parsec", "dbus-parsec",
"dnsmasq",
"dosfstools", "dosfstools",
"dracut-config-generic", "dracut-config-generic",
"dracut-network", "dracut-network",
@ -183,6 +182,13 @@ func iotCommitPackageSet(t *imageType) rpmmd.PackageSet {
}, },
}) })
} }
if common.VersionLessThan(t.arch.distro.osVersion, "41") {
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"dnsmasq", // deprecated for F41+
},
})
}
if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "41") { if common.VersionGreaterThanOrEqual(t.arch.distro.osVersion, "41") {
ps = ps.Append(rpmmd.PackageSet{ ps = ps.Append(rpmmd.PackageSet{
Include: []string{ Include: []string{
@ -653,7 +659,6 @@ func iotSimplifiedInstallerPackageSet(t *imageType) rpmmd.PackageSet {
"coreos-installer-dracut", "coreos-installer-dracut",
"coreutils", "coreutils",
"device-mapper-multipath", "device-mapper-multipath",
"dnsmasq",
"dosfstools", "dosfstools",
"dracut-live", "dracut-live",
"e2fsprogs", "e2fsprogs",
@ -697,6 +702,13 @@ func iotSimplifiedInstallerPackageSet(t *imageType) rpmmd.PackageSet {
}, },
}) })
} }
if common.VersionLessThan(t.arch.distro.osVersion, "41") {
ps = ps.Append(rpmmd.PackageSet{
Include: []string{
"dnsmasq", // deprecated for F41+
},
})
}
return ps return ps
} }

View file

@ -495,7 +495,7 @@ func EdgeInstallerImage(workload workload.Workload,
// kickstart though kickstart does support setting them // kickstart though kickstart does support setting them
img.Kickstart.Timezone, _ = customizations.GetTimezoneSettings() img.Kickstart.Timezone, _ = customizations.GetTimezoneSettings()
img.SquashfsCompression = "xz" img.RootfsCompression = "xz"
if t.Arch().Distro().Releasever() == "10" { if t.Arch().Distro().Releasever() == "10" {
img.RootfsType = manifest.SquashfsRootfs img.RootfsType = manifest.SquashfsRootfs
} }
@ -537,6 +537,10 @@ func EdgeInstallerImage(workload workload.Workload,
img.Filename = t.Filename() img.Filename = t.Filename()
if locale := t.getDefaultImageConfig().Locale; locale != nil {
img.Locale = *locale
}
return img, nil return img, nil
} }
@ -716,7 +720,7 @@ func ImageInstallerImage(workload workload.Workload,
} }
img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, anaconda.ModuleUsers) img.AdditionalAnacondaModules = append(img.AdditionalAnacondaModules, anaconda.ModuleUsers)
img.SquashfsCompression = "xz" img.RootfsCompression = "xz"
if t.Arch().Distro().Releasever() == "10" { if t.Arch().Distro().Releasever() == "10" {
img.RootfsType = manifest.SquashfsRootfs img.RootfsType = manifest.SquashfsRootfs
} }

View file

@ -166,8 +166,6 @@ const (
// default EC2 images config (common for all architectures) // default EC2 images config (common for all architectures)
func defaultEc2ImageConfig() *distro.ImageConfig { func defaultEc2ImageConfig() *distro.ImageConfig {
return &distro.ImageConfig{ return &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
Timezone: common.ToPtr("UTC"),
TimeSynchronization: &osbuild.ChronyStageOptions{ TimeSynchronization: &osbuild.ChronyStageOptions{
Servers: []osbuild.ChronyConfigServer{ Servers: []osbuild.ChronyConfigServer{
{ {

View file

@ -406,8 +406,6 @@ const defaultAzureKernelOptions = "ro loglevel=3 console=tty1 console=ttyS0 earl
// based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure // based on https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/deploying_rhel_9_on_microsoft_azure/assembly_deploying-a-rhel-image-as-a-virtual-machine-on-microsoft-azure_cloud-content-azure#making-configuration-changes_configure-the-image-azure
func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig { func defaultAzureImageConfig(rd *rhel.Distribution) *distro.ImageConfig {
ic := &distro.ImageConfig{ ic := &distro.ImageConfig{
Timezone: common.ToPtr("Etc/UTC"),
Locale: common.ToPtr("en_US.UTF-8"),
Keyboard: &osbuild.KeymapStageOptions{ Keyboard: &osbuild.KeymapStageOptions{
Keymap: "us", Keymap: "us",
X11Keymap: &osbuild.X11KeymapOptions{ X11Keymap: &osbuild.X11KeymapOptions{

View file

@ -51,7 +51,7 @@ func distroISOLabelFunc(t *rhel.ImageType) string {
func defaultDistroImageConfig(d *rhel.Distribution) *distro.ImageConfig { func defaultDistroImageConfig(d *rhel.Distribution) *distro.ImageConfig {
return &distro.ImageConfig{ return &distro.ImageConfig{
Timezone: common.ToPtr("America/New_York"), Timezone: common.ToPtr("UTC"),
Locale: common.ToPtr("C.UTF-8"), Locale: common.ToPtr("C.UTF-8"),
Sysconfig: []*osbuild.SysconfigStageOptions{ Sysconfig: []*osbuild.SysconfigStageOptions{
{ {

View file

@ -37,7 +37,6 @@ func mkGCEImageType() *rhel.ImageType {
func baseGCEImageConfig() *distro.ImageConfig { func baseGCEImageConfig() *distro.ImageConfig {
ic := &distro.ImageConfig{ ic := &distro.ImageConfig{
Timezone: common.ToPtr("UTC"),
TimeSynchronization: &osbuild.ChronyStageOptions{ TimeSynchronization: &osbuild.ChronyStageOptions{
Servers: []osbuild.ChronyConfigServer{{Hostname: "metadata.google.internal"}}, Servers: []osbuild.ChronyConfigServer{{Hostname: "metadata.google.internal"}},
}, },
@ -59,7 +58,6 @@ func baseGCEImageConfig() *distro.ImageConfig {
"reboot.target", "reboot.target",
}, },
DefaultTarget: common.ToPtr("multi-user.target"), DefaultTarget: common.ToPtr("multi-user.target"),
Locale: common.ToPtr("en_US.UTF-8"),
Keyboard: &osbuild.KeymapStageOptions{ Keyboard: &osbuild.KeymapStageOptions{
Keymap: "us", Keymap: "us",
}, },

View file

@ -23,7 +23,6 @@ func mkWSLImgType() *rhel.ImageType {
) )
it.DefaultImageConfig = &distro.ImageConfig{ it.DefaultImageConfig = &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
NoSElinux: common.ToPtr(true), NoSElinux: common.ToPtr(true),
WSLConfig: &osbuild.WSLConfStageOptions{ WSLConfig: &osbuild.WSLConfStageOptions{
Boot: osbuild.WSLConfBootOptions{ Boot: osbuild.WSLConfBootOptions{

View file

@ -1,9 +1,7 @@
package rhel10 package rhel10
import ( import (
"github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/datasizes" "github.com/osbuild/images/pkg/datasizes"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/rhel" "github.com/osbuild/images/pkg/distro/rhel"
"github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/rpmmd"
) )
@ -24,9 +22,6 @@ func mkVMDKImgType() *rhel.ImageType {
[]string{"vmdk"}, []string{"vmdk"},
) )
it.DefaultImageConfig = &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
}
it.KernelOptions = vmdkKernelOptions it.KernelOptions = vmdkKernelOptions
it.Bootable = true it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte it.DefaultSize = 4 * datasizes.GibiByte
@ -49,9 +44,6 @@ func mkOVAImgType() *rhel.ImageType {
[]string{"archive"}, []string{"archive"},
) )
it.DefaultImageConfig = &distro.ImageConfig{
Locale: common.ToPtr("en_US.UTF-8"),
}
it.KernelOptions = vmdkKernelOptions it.KernelOptions = vmdkKernelOptions
it.Bootable = true it.Bootable = true
it.DefaultSize = 4 * datasizes.GibiByte it.DefaultSize = 4 * datasizes.GibiByte

View file

@ -62,6 +62,10 @@ func mkImageInstallerImgType() *rhel.ImageType {
}, },
} }
it.DefaultImageConfig = &distro.ImageConfig{
Locale: common.ToPtr("C.UTF-8"),
}
return it return it
} }

View file

@ -586,6 +586,8 @@ func (result depsolveResult) toRPMMD(rhsm map[string]bool) ([]rpmmd.PackageSpec,
rpmDependencies[i].RemoteLocation = dep.RemoteLocation rpmDependencies[i].RemoteLocation = dep.RemoteLocation
rpmDependencies[i].Checksum = dep.Checksum rpmDependencies[i].Checksum = dep.Checksum
rpmDependencies[i].CheckGPG = repo.GPGCheck rpmDependencies[i].CheckGPG = repo.GPGCheck
rpmDependencies[i].RepoID = dep.RepoID
rpmDependencies[i].Path = dep.Path
if verify := repo.SSLVerify; verify != nil { if verify := repo.SSLVerify; verify != nil {
rpmDependencies[i].IgnoreSSL = !*verify rpmDependencies[i].IgnoreSSL = !*verify
} }

View file

@ -22,8 +22,8 @@ type AnacondaContainerInstaller struct {
Platform platform.Platform Platform platform.Platform
ExtraBasePackages rpmmd.PackageSet ExtraBasePackages rpmmd.PackageSet
SquashfsCompression string RootfsCompression string
RootfsType manifest.RootfsType RootfsType manifest.RootfsType
ISOLabel string ISOLabel string
Product string Product string
@ -51,6 +51,10 @@ type AnacondaContainerInstaller struct {
// Uses the old, deprecated, Anaconda config option "kickstart-modules". // Uses the old, deprecated, Anaconda config option "kickstart-modules".
// Only for RHEL 8. // Only for RHEL 8.
UseLegacyAnacondaConfig bool UseLegacyAnacondaConfig bool
// Locale for the installer. This should be set to the same locale as the
// ISO OS payload, if known.
Locale string
} }
func NewAnacondaContainerInstaller(container container.SourceSpec, ref string) *AnacondaContainerInstaller { func NewAnacondaContainerInstaller(container container.SourceSpec, ref string) *AnacondaContainerInstaller {
@ -98,6 +102,7 @@ func (img *AnacondaContainerInstaller) InstantiateManifest(m *manifest.Manifest,
) )
} }
anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers
anacondaPipeline.Locale = img.Locale
var rootfsImagePipeline *manifest.ISORootfsImg var rootfsImagePipeline *manifest.ISORootfsImg
switch img.RootfsType { switch img.RootfsType {
@ -132,7 +137,8 @@ func (img *AnacondaContainerInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.Release = img.Release isoTreePipeline.Release = img.Release
isoTreePipeline.Kickstart = img.Kickstart isoTreePipeline.Kickstart = img.Kickstart
isoTreePipeline.SquashfsCompression = img.SquashfsCompression isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType
// For ostree installers, always put the kickstart file in the root of the ISO // For ostree installers, always put the kickstart file in the root of the ISO
isoTreePipeline.PayloadPath = "/container" isoTreePipeline.PayloadPath = "/container"

View file

@ -23,8 +23,8 @@ type AnacondaLiveInstaller struct {
ExtraBasePackages rpmmd.PackageSet ExtraBasePackages rpmmd.PackageSet
SquashfsCompression string RootfsCompression string
RootfsType manifest.RootfsType RootfsType manifest.RootfsType
ISOLabel string ISOLabel string
Product string Product string
@ -36,6 +36,10 @@ type AnacondaLiveInstaller struct {
Filename string Filename string
AdditionalKernelOpts []string AdditionalKernelOpts []string
// Locale for the installer. This should be set to the same locale as the
// ISO OS payload, if known.
Locale string
} }
func NewAnacondaLiveInstaller() *AnacondaLiveInstaller { func NewAnacondaLiveInstaller() *AnacondaLiveInstaller {
@ -67,6 +71,7 @@ func (img *AnacondaLiveInstaller) InstantiateManifest(m *manifest.Manifest,
livePipeline.Variant = img.Variant livePipeline.Variant = img.Variant
livePipeline.Biosdevname = (img.Platform.GetArch() == arch.ARCH_X86_64) livePipeline.Biosdevname = (img.Platform.GetArch() == arch.ARCH_X86_64)
livePipeline.Locale = img.Locale
// The live installer has SElinux enabled and targeted // The live installer has SElinux enabled and targeted
livePipeline.SElinux = "targeted" livePipeline.SElinux = "targeted"
@ -107,7 +112,8 @@ func (img *AnacondaLiveInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.KernelOpts = kernelOpts isoTreePipeline.KernelOpts = kernelOpts
isoTreePipeline.ISOLinux = isoLinuxEnabled isoTreePipeline.ISOLinux = isoLinuxEnabled
isoTreePipeline.SquashfsCompression = img.SquashfsCompression isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType
isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel) isoPipeline := manifest.NewISO(buildPipeline, isoTreePipeline, img.ISOLabel)
isoPipeline.SetFilename(img.Filename) isoPipeline.SetFilename(img.Filename)

View file

@ -28,8 +28,8 @@ type AnacondaOSTreeInstaller struct {
// Subscription options to include // Subscription options to include
Subscription *subscription.ImageOptions Subscription *subscription.ImageOptions
SquashfsCompression string RootfsCompression string
RootfsType manifest.RootfsType RootfsType manifest.RootfsType
ISOLabel string ISOLabel string
Product string Product string
@ -51,6 +51,10 @@ type AnacondaOSTreeInstaller struct {
// Uses the old, deprecated, Anaconda config option "kickstart-modules". // Uses the old, deprecated, Anaconda config option "kickstart-modules".
// Only for RHEL 8. // Only for RHEL 8.
UseLegacyAnacondaConfig bool UseLegacyAnacondaConfig bool
// Locale for the installer. This should be set to the same locale as the
// ISO OS payload, if known.
Locale string
} }
func NewAnacondaOSTreeInstaller(commit ostree.SourceSpec) *AnacondaOSTreeInstaller { func NewAnacondaOSTreeInstaller(commit ostree.SourceSpec) *AnacondaOSTreeInstaller {
@ -101,6 +105,7 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
} }
anacondaPipeline.DisabledAnacondaModules = img.DisabledAnacondaModules anacondaPipeline.DisabledAnacondaModules = img.DisabledAnacondaModules
anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers
anacondaPipeline.Locale = img.Locale
var rootfsImagePipeline *manifest.ISORootfsImg var rootfsImagePipeline *manifest.ISORootfsImg
switch img.RootfsType { switch img.RootfsType {
@ -139,7 +144,8 @@ func (img *AnacondaOSTreeInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.PartitionTable = efiBootPartitionTable(rng) isoTreePipeline.PartitionTable = efiBootPartitionTable(rng)
isoTreePipeline.Release = img.Release isoTreePipeline.Release = img.Release
isoTreePipeline.Kickstart = img.Kickstart isoTreePipeline.Kickstart = img.Kickstart
isoTreePipeline.SquashfsCompression = img.SquashfsCompression isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType
isoTreePipeline.PayloadPath = "/ostree/repo" isoTreePipeline.PayloadPath = "/ostree/repo"

View file

@ -56,8 +56,8 @@ type AnacondaTarInstaller struct {
ISORootKickstart bool ISORootKickstart bool
Kickstart *kickstart.Options Kickstart *kickstart.Options
SquashfsCompression string RootfsCompression string
RootfsType manifest.RootfsType RootfsType manifest.RootfsType
ISOLabel string ISOLabel string
Product string Product string
@ -144,6 +144,7 @@ func (img *AnacondaTarInstaller) InstantiateManifest(m *manifest.Manifest,
anacondaPipeline.DisabledAnacondaModules = img.DisabledAnacondaModules anacondaPipeline.DisabledAnacondaModules = img.DisabledAnacondaModules
anacondaPipeline.AdditionalDracutModules = img.AdditionalDracutModules anacondaPipeline.AdditionalDracutModules = img.AdditionalDracutModules
anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers anacondaPipeline.AdditionalDrivers = img.AdditionalDrivers
anacondaPipeline.Locale = img.OSCustomizations.Language
tarPath := "/liveimg.tar.gz" tarPath := "/liveimg.tar.gz"
@ -195,7 +196,8 @@ func (img *AnacondaTarInstaller) InstantiateManifest(m *manifest.Manifest,
isoTreePipeline.Kickstart.Path = img.Kickstart.Path isoTreePipeline.Kickstart.Path = img.Kickstart.Path
} }
isoTreePipeline.SquashfsCompression = img.SquashfsCompression isoTreePipeline.RootfsCompression = img.RootfsCompression
isoTreePipeline.RootfsType = img.RootfsType
isoTreePipeline.OSPipeline = osPipeline isoTreePipeline.OSPipeline = osPipeline
isoTreePipeline.KernelOpts = img.AdditionalKernelOpts isoTreePipeline.KernelOpts = img.AdditionalKernelOpts

View file

@ -6,12 +6,10 @@ import (
"github.com/osbuild/images/internal/common" "github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/arch" "github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fsnode" "github.com/osbuild/images/pkg/customizations/fsnode"
"github.com/osbuild/images/pkg/customizations/kickstart" "github.com/osbuild/images/pkg/customizations/kickstart"
"github.com/osbuild/images/pkg/customizations/users" "github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/platform" "github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/rpmmd"
) )
@ -89,6 +87,10 @@ type AnacondaInstaller struct {
// tree with the selected profile and selects the required package // tree with the selected profile and selects the required package
// for depsolving // for depsolving
SElinux string SElinux string
// Locale for the installer. This should be set to the same locale as the
// ISO OS payload, if known.
Locale string
} }
func NewAnacondaInstaller(installerType AnacondaInstallerType, func NewAnacondaInstaller(installerType AnacondaInstallerType,
@ -196,15 +198,15 @@ func (p *AnacondaInstaller) getPackageSpecs() []rpmmd.PackageSpec {
return p.packageSpecs return p.packageSpecs
} }
func (p *AnacondaInstaller) serializeStart(packages []rpmmd.PackageSpec, _ []container.Spec, _ []ostree.CommitSpec, rpmRepos []rpmmd.RepoConfig) { func (p *AnacondaInstaller) serializeStart(inputs Inputs) {
if len(p.packageSpecs) > 0 { if len(p.packageSpecs) > 0 {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
p.packageSpecs = packages p.packageSpecs = inputs.Depsolved.Packages
if p.kernelName != "" { if p.kernelName != "" {
p.kernelVer = rpmmd.GetVerStrFromPackageSpecListPanic(p.packageSpecs, p.kernelName) p.kernelVer = rpmmd.GetVerStrFromPackageSpecListPanic(p.packageSpecs, p.kernelName)
} }
p.repos = append(p.repos, rpmRepos...) p.repos = append(p.repos, inputs.Depsolved.Repos...)
} }
func (p *AnacondaInstaller) serializeEnd() { func (p *AnacondaInstaller) serializeEnd() {
@ -236,7 +238,13 @@ func (p *AnacondaInstaller) serialize() osbuild.Pipeline {
Version: p.version, Version: p.version,
Final: !p.preview, Final: !p.preview,
})) }))
pipeline.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: "en_US.UTF-8"}))
locale := p.Locale
if locale == "" {
// default to C.UTF-8 if unset
locale = "C.UTF-8"
}
pipeline.AddStage(osbuild.NewLocaleStage(&osbuild.LocaleStageOptions{Language: locale}))
// Let's do a bunch of sanity checks that are dependent on the installer type // Let's do a bunch of sanity checks that are dependent on the installer type
// being serialized // being serialized

View file

@ -14,7 +14,6 @@ import (
"github.com/osbuild/images/pkg/disk" "github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree" "github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/rpmmd"
) )
type RootfsType uint64 type RootfsType uint64
@ -23,6 +22,7 @@ type RootfsType uint64
const ( // Rootfs type enum const ( // Rootfs type enum
SquashfsExt4Rootfs RootfsType = iota // Create an EXT4 rootfs compressed by Squashfs SquashfsExt4Rootfs RootfsType = iota // Create an EXT4 rootfs compressed by Squashfs
SquashfsRootfs // Create a plain squashfs rootfs SquashfsRootfs // Create a plain squashfs rootfs
ErofsRootfs // Create a plain erofs rootfs
) )
// An AnacondaInstallerISOTree represents a tree containing the anaconda installer, // An AnacondaInstallerISOTree represents a tree containing the anaconda installer,
@ -49,7 +49,8 @@ type AnacondaInstallerISOTree struct {
isoLabel string isoLabel string
SquashfsCompression string RootfsCompression string
RootfsType RootfsType
OSPipeline *OS OSPipeline *OS
OSTreeCommitSource *ostree.SourceSpec OSTreeCommitSource *ostree.SourceSpec
@ -135,8 +136,13 @@ func (p *AnacondaInstallerISOTree) getInline() []string {
return inlineData return inlineData
} }
func (p *AnacondaInstallerISOTree) getBuildPackages(_ Distro) []string { func (p *AnacondaInstallerISOTree) getBuildPackages(_ Distro) []string {
packages := []string{ var packages []string
"squashfs-tools", switch p.RootfsType {
case SquashfsExt4Rootfs, SquashfsRootfs:
packages = []string{"squashfs-tools"}
case ErofsRootfs:
packages = []string{"erofs-utils"}
default:
} }
if p.OSTreeCommitSource != nil { if p.OSTreeCommitSource != nil {
@ -154,25 +160,91 @@ func (p *AnacondaInstallerISOTree) getBuildPackages(_ Distro) []string {
return packages return packages
} }
func (p *AnacondaInstallerISOTree) serializeStart(_ []rpmmd.PackageSpec, containers []container.Spec, commits []ostree.CommitSpec, _ []rpmmd.RepoConfig) { // NewSquashfsStage returns an osbuild stage configured to build
// the squashfs root filesystem for the ISO.
func (p *AnacondaInstallerISOTree) NewSquashfsStage() *osbuild.Stage {
var squashfsOptions osbuild.SquashfsStageOptions
if p.anacondaPipeline.Type == AnacondaInstallerTypePayload {
squashfsOptions = osbuild.SquashfsStageOptions{
Filename: "images/install.img",
}
} else if p.anacondaPipeline.Type == AnacondaInstallerTypeLive {
squashfsOptions = osbuild.SquashfsStageOptions{
Filename: "LiveOS/squashfs.img",
}
}
if p.RootfsCompression != "" {
squashfsOptions.Compression.Method = p.RootfsCompression
} else {
// default to xz if not specified
squashfsOptions.Compression.Method = "xz"
}
if squashfsOptions.Compression.Method == "xz" {
squashfsOptions.Compression.Options = &osbuild.FSCompressionOptions{
BCJ: osbuild.BCJOption(p.anacondaPipeline.platform.GetArch().String()),
}
}
// The iso's rootfs can either be an ext4 filesystem compressed with squashfs, or
// a squashfs of the plain directory tree
if p.RootfsType == SquashfsExt4Rootfs && p.rootfsPipeline != nil {
return osbuild.NewSquashfsStage(&squashfsOptions, p.rootfsPipeline.Name())
}
return osbuild.NewSquashfsStage(&squashfsOptions, p.anacondaPipeline.Name())
}
// NewErofsStage returns an osbuild stage configured to build
// the erofs root filesystem for the ISO.
func (p *AnacondaInstallerISOTree) NewErofsStage() *osbuild.Stage {
var erofsOptions osbuild.ErofsStageOptions
if p.anacondaPipeline.Type == AnacondaInstallerTypePayload {
erofsOptions = osbuild.ErofsStageOptions{
Filename: "images/install.img",
}
} else if p.anacondaPipeline.Type == AnacondaInstallerTypeLive {
erofsOptions = osbuild.ErofsStageOptions{
Filename: "LiveOS/squashfs.img",
}
}
var compression osbuild.ErofsCompression
if p.RootfsCompression != "" {
compression.Method = p.RootfsCompression
} else {
// default to zstd if not specified
compression.Method = "zstd"
}
compression.Level = common.ToPtr(8)
erofsOptions.Compression = &compression
erofsOptions.ExtendedOptions = []string{"all-fragments", "dedupe"}
erofsOptions.ClusterSize = common.ToPtr(131072)
return osbuild.NewErofsStage(&erofsOptions, p.anacondaPipeline.Name())
}
func (p *AnacondaInstallerISOTree) serializeStart(inputs Inputs) {
if p.ostreeCommitSpec != nil || p.containerSpec != nil { if p.ostreeCommitSpec != nil || p.containerSpec != nil {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
if len(commits) > 1 { if len(inputs.Commits) > 1 {
panic("pipeline supports at most one ostree commit") panic("pipeline supports at most one ostree commit")
} }
if len(containers) > 1 { if len(inputs.Containers) > 1 {
panic("pipeline supports at most one container") panic("pipeline supports at most one container")
} }
if len(commits) > 0 { if len(inputs.Commits) > 0 {
p.ostreeCommitSpec = &commits[0] p.ostreeCommitSpec = &inputs.Commits[0]
} }
if len(containers) > 0 { if len(inputs.Containers) > 0 {
p.containerSpec = &containers[0] p.containerSpec = &inputs.Containers[0]
} }
} }
@ -261,41 +333,15 @@ func (p *AnacondaInstallerISOTree) serialize() osbuild.Pipeline {
copyStage := osbuild.NewCopyStageSimple(copyStageOptions, copyStageInputs) copyStage := osbuild.NewCopyStageSimple(copyStageOptions, copyStageInputs)
pipeline.AddStage(copyStage) pipeline.AddStage(copyStage)
var squashfsOptions osbuild.SquashfsStageOptions // Add the selected roofs stage
switch p.RootfsType {
if p.anacondaPipeline.Type == AnacondaInstallerTypePayload { case SquashfsExt4Rootfs, SquashfsRootfs:
squashfsOptions = osbuild.SquashfsStageOptions{ pipeline.AddStage(p.NewSquashfsStage())
Filename: "images/install.img", case ErofsRootfs:
} pipeline.AddStage(p.NewErofsStage())
} else if p.anacondaPipeline.Type == AnacondaInstallerTypeLive { default:
squashfsOptions = osbuild.SquashfsStageOptions{
Filename: "LiveOS/squashfs.img",
}
} }
if p.SquashfsCompression != "" {
squashfsOptions.Compression.Method = p.SquashfsCompression
} else {
// default to xz if not specified
squashfsOptions.Compression.Method = "xz"
}
if squashfsOptions.Compression.Method == "xz" {
squashfsOptions.Compression.Options = &osbuild.FSCompressionOptions{
BCJ: osbuild.BCJOption(p.anacondaPipeline.platform.GetArch().String()),
}
}
// The iso's rootfs can either be an ext4 filesystem compressed with squashfs, or
// a squashfs of the plain directory tree
var squashfsStage *osbuild.Stage
if p.rootfsPipeline != nil {
squashfsStage = osbuild.NewSquashfsStage(&squashfsOptions, p.rootfsPipeline.Name())
} else {
squashfsStage = osbuild.NewSquashfsStage(&squashfsOptions, p.anacondaPipeline.Name())
}
pipeline.AddStage(squashfsStage)
if p.ISOLinux { if p.ISOLinux {
isoLinuxOptions := &osbuild.ISOLinuxStageOptions{ isoLinuxOptions := &osbuild.ISOLinuxStageOptions{
Product: osbuild.ISOLinuxProduct{ Product: osbuild.ISOLinuxProduct{
@ -526,12 +572,13 @@ reboot --eject
` `
// Workaround for lack of --target-imgref in Anaconda, xref https://github.com/osbuild/images/issues/380 // Workaround for lack of --target-imgref in Anaconda, xref https://github.com/osbuild/images/issues/380
hardcodedKickstartBits += fmt.Sprintf(`%%post hardcodedKickstartBits += fmt.Sprintf(`%%post --erroronfail
bootc switch --mutate-in-place --transport %s %s bootc switch --mutate-in-place --transport %s %s
# used during automatic image testing as finished marker # used during automatic image testing as finished marker
if [ -c /dev/ttyS0 ]; then if [ -c /dev/ttyS0 ]; then
echo "Install finished" > /dev/ttyS0 # continue on errors here, because we used to omit --erroronfail
echo "Install finished" > /dev/ttyS0 || true
fi fi
%%end %%end
`, targetContainerTransport, p.containerSpec.LocalName) `, targetContainerTransport, p.containerSpec.LocalName)

View file

@ -5,7 +5,6 @@ import (
"github.com/osbuild/images/pkg/container" "github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/rpmmd"
"github.com/osbuild/images/pkg/runner" "github.com/osbuild/images/pkg/runner"
) )
@ -99,12 +98,12 @@ func (p *BuildrootFromPackages) getPackageSpecs() []rpmmd.PackageSpec {
return p.packageSpecs return p.packageSpecs
} }
func (p *BuildrootFromPackages) serializeStart(packages []rpmmd.PackageSpec, _ []container.Spec, _ []ostree.CommitSpec, rpmRepos []rpmmd.RepoConfig) { func (p *BuildrootFromPackages) serializeStart(inputs Inputs) {
if len(p.packageSpecs) > 0 { if len(p.packageSpecs) > 0 {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
p.packageSpecs = packages p.packageSpecs = inputs.Depsolved.Packages
p.repos = append(p.repos, rpmRepos...) p.repos = append(p.repos, inputs.Depsolved.Repos...)
} }
func (p *BuildrootFromPackages) serializeEnd() { func (p *BuildrootFromPackages) serializeEnd() {
@ -199,11 +198,11 @@ func (p *BuildrootFromContainer) getContainerSpecs() []container.Spec {
return p.containerSpecs return p.containerSpecs
} }
func (p *BuildrootFromContainer) serializeStart(_ []rpmmd.PackageSpec, containerSpecs []container.Spec, _ []ostree.CommitSpec, _ []rpmmd.RepoConfig) { func (p *BuildrootFromContainer) serializeStart(inputs Inputs) {
if len(p.containerSpecs) > 0 { if len(p.containerSpecs) > 0 {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
p.containerSpecs = containerSpecs p.containerSpecs = inputs.Containers
} }
func (p *BuildrootFromContainer) serializeEnd() { func (p *BuildrootFromContainer) serializeEnd() {

View file

@ -4,9 +4,7 @@ import (
"path/filepath" "path/filepath"
"github.com/osbuild/images/internal/common" "github.com/osbuild/images/internal/common"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/platform" "github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/rpmmd"
) )
@ -80,12 +78,12 @@ func (p *OSTreeCommitServer) getPackageSpecs() []rpmmd.PackageSpec {
return p.packageSpecs return p.packageSpecs
} }
func (p *OSTreeCommitServer) serializeStart(packages []rpmmd.PackageSpec, _ []container.Spec, _ []ostree.CommitSpec, rpmRepos []rpmmd.RepoConfig) { func (p *OSTreeCommitServer) serializeStart(inputs Inputs) {
if len(p.packageSpecs) > 0 { if len(p.packageSpecs) > 0 {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
p.packageSpecs = packages p.packageSpecs = inputs.Depsolved.Packages
p.repos = append(p.repos, rpmRepos...) p.repos = append(p.repos, inputs.Depsolved.Repos...)
} }
func (p *OSTreeCommitServer) serializeEnd() { func (p *OSTreeCommitServer) serializeEnd() {

View file

@ -4,11 +4,9 @@ import (
"fmt" "fmt"
"github.com/osbuild/images/pkg/arch" "github.com/osbuild/images/pkg/arch"
"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/customizations/fdo" "github.com/osbuild/images/pkg/customizations/fdo"
"github.com/osbuild/images/pkg/customizations/ignition" "github.com/osbuild/images/pkg/customizations/ignition"
"github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/platform" "github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/rpmmd"
) )
@ -136,15 +134,15 @@ func (p *CoreOSInstaller) getPackageSpecs() []rpmmd.PackageSpec {
return p.packageSpecs return p.packageSpecs
} }
func (p *CoreOSInstaller) serializeStart(packages []rpmmd.PackageSpec, _ []container.Spec, _ []ostree.CommitSpec, rpmRepos []rpmmd.RepoConfig) { func (p *CoreOSInstaller) serializeStart(inputs Inputs) {
if len(p.packageSpecs) > 0 { if len(p.packageSpecs) > 0 {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
p.packageSpecs = packages p.packageSpecs = inputs.Depsolved.Packages
if p.kernelName != "" { if p.kernelName != "" {
p.kernelVer = rpmmd.GetVerStrFromPackageSpecListPanic(p.packageSpecs, p.kernelName) p.kernelVer = rpmmd.GetVerStrFromPackageSpecListPanic(p.packageSpecs, p.kernelName)
} }
p.repos = append(p.repos, rpmRepos...) p.repos = append(p.repos, inputs.Depsolved.Repos...)
} }
func (p *CoreOSInstaller) getInline() []string { func (p *CoreOSInstaller) getInline() []string {

View file

@ -65,14 +65,14 @@ func (p *ContentTest) getOSTreeCommits() []ostree.CommitSpec {
return p.commitSpecs return p.commitSpecs
} }
func (p *ContentTest) serializeStart(pkgs []rpmmd.PackageSpec, containers []container.Spec, commits []ostree.CommitSpec, rpmRepos []rpmmd.RepoConfig) { func (p *ContentTest) serializeStart(inputs Inputs) {
if p.serializing { if p.serializing {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
p.packageSpecs = pkgs p.packageSpecs = inputs.Depsolved.Packages
p.containerSpecs = containers p.containerSpecs = inputs.Containers
p.commitSpecs = commits p.commitSpecs = inputs.Commits
p.repos = rpmRepos p.repos = inputs.Depsolved.Repos
p.serializing = true p.serializing = true
} }

View file

@ -16,6 +16,7 @@ import (
"encoding/json" "encoding/json"
"github.com/osbuild/images/pkg/container" "github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/dnfjson"
"github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree" "github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/rpmmd"
@ -41,6 +42,8 @@ const (
DISTRO_FEDORA DISTRO_FEDORA
) )
type Inputs osbuild.SourceInputs
// An OSBuildManifest is an opaque JSON object, which is a valid input to osbuild // An OSBuildManifest is an opaque JSON object, which is a valid input to osbuild
type OSBuildManifest []byte type OSBuildManifest []byte
@ -138,27 +141,39 @@ func (m Manifest) GetOSTreeSourceSpecs() map[string][]ostree.SourceSpec {
return ostreeSpecs return ostreeSpecs
} }
func (m Manifest) Serialize(packageSets map[string][]rpmmd.PackageSpec, containerSpecs map[string][]container.Spec, ostreeCommits map[string][]ostree.CommitSpec, rpmRepos map[string][]rpmmd.RepoConfig) (OSBuildManifest, error) { type SerializeOptions struct {
pipelines := make([]osbuild.Pipeline, 0) RpmDownloader osbuild.RpmDownloader
packages := make([]rpmmd.PackageSpec, 0) }
commits := make([]ostree.CommitSpec, 0)
inline := make([]string, 0) func (m Manifest) Serialize(depsolvedSets map[string]dnfjson.DepsolveResult, containerSpecs map[string][]container.Spec, ostreeCommits map[string][]ostree.CommitSpec, opts *SerializeOptions) (OSBuildManifest, error) {
containers := make([]container.Spec, 0) if opts == nil {
for _, pipeline := range m.pipelines { opts = &SerializeOptions{}
pipeline.serializeStart(packageSets[pipeline.Name()], containerSpecs[pipeline.Name()], ostreeCommits[pipeline.Name()], rpmRepos[pipeline.Name()])
} }
for _, pipeline := range m.pipelines {
pipeline.serializeStart(Inputs{
Depsolved: depsolvedSets[pipeline.Name()],
Containers: containerSpecs[pipeline.Name()],
Commits: ostreeCommits[pipeline.Name()],
})
}
var pipelines []osbuild.Pipeline
var mergedInputs osbuild.SourceInputs
for _, pipeline := range m.pipelines { for _, pipeline := range m.pipelines {
commits = append(commits, pipeline.getOSTreeCommits()...)
pipelines = append(pipelines, pipeline.serialize()) pipelines = append(pipelines, pipeline.serialize())
packages = append(packages, packageSets[pipeline.Name()]...)
inline = append(inline, pipeline.getInline()...) mergedInputs.Commits = append(mergedInputs.Commits, pipeline.getOSTreeCommits()...)
containers = append(containers, pipeline.getContainerSpecs()...) mergedInputs.Depsolved.Packages = append(mergedInputs.Depsolved.Packages, depsolvedSets[pipeline.Name()].Packages...)
mergedInputs.Depsolved.Repos = append(mergedInputs.Depsolved.Repos, depsolvedSets[pipeline.Name()].Repos...)
mergedInputs.Containers = append(mergedInputs.Containers, pipeline.getContainerSpecs()...)
mergedInputs.InlineData = append(mergedInputs.InlineData, pipeline.getInline()...)
} }
for _, pipeline := range m.pipelines { for _, pipeline := range m.pipelines {
pipeline.serializeEnd() pipeline.serializeEnd()
} }
sources, err := osbuild.GenSources(packages, commits, inline, containers) sources, err := osbuild.GenSources(mergedInputs, opts.RpmDownloader)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -376,25 +376,25 @@ func (p *OS) getContainerSpecs() []container.Spec {
return p.containerSpecs return p.containerSpecs
} }
func (p *OS) serializeStart(packages []rpmmd.PackageSpec, containers []container.Spec, commits []ostree.CommitSpec, rpmRepos []rpmmd.RepoConfig) { func (p *OS) serializeStart(inputs Inputs) {
if len(p.packageSpecs) > 0 { if len(p.packageSpecs) > 0 {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
p.packageSpecs = packages p.packageSpecs = inputs.Depsolved.Packages
p.containerSpecs = containers p.containerSpecs = inputs.Containers
if len(commits) > 0 { if len(inputs.Commits) > 0 {
if len(commits) > 1 { if len(inputs.Commits) > 1 {
panic("pipeline supports at most one ostree commit") panic("pipeline supports at most one ostree commit")
} }
p.ostreeParentSpec = &commits[0] p.ostreeParentSpec = &inputs.Commits[0]
} }
if p.KernelName != "" { if p.KernelName != "" {
p.kernelVer = rpmmd.GetVerStrFromPackageSpecListPanic(p.packageSpecs, p.KernelName) p.kernelVer = rpmmd.GetVerStrFromPackageSpecListPanic(p.packageSpecs, p.KernelName)
} }
p.repos = append(p.repos, rpmRepos...) p.repos = append(p.repos, inputs.Depsolved.Repos...)
} }
func (p *OS) serializeEnd() { func (p *OS) serializeEnd() {

View file

@ -13,7 +13,6 @@ import (
"github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree" "github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/platform" "github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/rpmmd"
) )
// OSTreeDeploymentCustomizations encapsulates all configuration applied to an // OSTreeDeploymentCustomizations encapsulates all configuration applied to an
@ -161,18 +160,18 @@ func (p *OSTreeDeployment) getContainerSources() []container.SourceSpec {
} }
} }
func (p *OSTreeDeployment) serializeStart(_ []rpmmd.PackageSpec, containers []container.Spec, commits []ostree.CommitSpec, _ []rpmmd.RepoConfig) { func (p *OSTreeDeployment) serializeStart(inputs Inputs) {
if p.ostreeSpec != nil || p.containerSpec != nil { if p.ostreeSpec != nil || p.containerSpec != nil {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
switch { switch {
case len(commits) == 1: case len(inputs.Commits) == 1:
p.ostreeSpec = &commits[0] p.ostreeSpec = &inputs.Commits[0]
case len(containers) == 1: case len(inputs.Containers) == 1:
p.containerSpec = &containers[0] p.containerSpec = &inputs.Containers[0]
default: default:
panic(fmt.Sprintf("pipeline %s requires exactly one ostree commit or one container (have commits: %v; containers: %v)", p.Name(), commits, containers)) panic(fmt.Sprintf("pipeline %s requires exactly one ostree commit or one container (have commits: %v; containers: %v)", p.Name(), inputs.Commits, inputs.Containers))
} }
} }

View file

@ -53,7 +53,7 @@ type Pipeline interface {
// its full Spec. See the ostree package for more details. // its full Spec. See the ostree package for more details.
getOSTreeCommitSources() []ostree.SourceSpec getOSTreeCommitSources() []ostree.SourceSpec
serializeStart([]rpmmd.PackageSpec, []container.Spec, []ostree.CommitSpec, []rpmmd.RepoConfig) serializeStart(Inputs)
serializeEnd() serializeEnd()
serialize() osbuild.Pipeline serialize() osbuild.Pipeline
@ -166,7 +166,7 @@ func NewBase(name string, build Build) Base {
// serializeStart must be called exactly once before each call // serializeStart must be called exactly once before each call
// to serialize(). // to serialize().
func (p Base) serializeStart([]rpmmd.PackageSpec, []container.Spec, []ostree.CommitSpec, []rpmmd.RepoConfig) { func (p Base) serializeStart(inputs Inputs) {
} }
// serializeEnd must be called exactly once after each call to // serializeEnd must be called exactly once after each call to

View file

@ -10,9 +10,7 @@ import (
"github.com/osbuild/images/pkg/customizations/users" "github.com/osbuild/images/pkg/customizations/users"
"github.com/osbuild/images/pkg/disk" "github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/osbuild" "github.com/osbuild/images/pkg/osbuild"
"github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/platform" "github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/rpmmd"
) )
// A RawBootcImage represents a raw bootc image file which can be booted in a // A RawBootcImage represents a raw bootc image file which can be booted in a
@ -71,11 +69,11 @@ func (p *RawBootcImage) getContainerSpecs() []container.Spec {
return p.containerSpecs return p.containerSpecs
} }
func (p *RawBootcImage) serializeStart(_ []rpmmd.PackageSpec, containerSpecs []container.Spec, _ []ostree.CommitSpec, _ []rpmmd.RepoConfig) { func (p *RawBootcImage) serializeStart(inputs Inputs) {
if len(p.containerSpecs) > 0 { if len(p.containerSpecs) > 0 {
panic("double call to serializeStart()") panic("double call to serializeStart()")
} }
p.containerSpecs = containerSpecs p.containerSpecs = inputs.Containers
} }
func (p *RawBootcImage) serializeEnd() { func (p *RawBootcImage) serializeEnd() {

View file

@ -9,6 +9,8 @@ import (
"github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/rpmmd"
) )
const SourceNameCurl = "org.osbuild.curl"
var curlDigestPattern = regexp.MustCompile(`(md5|sha1|sha256|sha384|sha512):[0-9a-f]{32,128}`) var curlDigestPattern = regexp.MustCompile(`(md5|sha1|sha256|sha384|sha512):[0-9a-f]{32,128}`)
type CurlSource struct { type CurlSource struct {

View file

@ -0,0 +1,24 @@
package osbuild
type ErofsCompression struct {
Method string `json:"method"`
Level *int `json:"level,omitempty"`
}
type ErofsStageOptions struct {
Filename string `json:"filename"`
Compression *ErofsCompression `json:"compression,omitempty"`
ExtendedOptions []string `json:"options,omitempty"`
ClusterSize *int `json:"cluster-size,omitempty"`
}
func (ErofsStageOptions) isStageOptions() {}
func NewErofsStage(options *ErofsStageOptions, inputPipeline string) *Stage {
return &Stage{
Type: "org.osbuild.erofs",
Options: options,
Inputs: NewPipelineTreeInputs("tree", inputPipeline),
}
}

View file

@ -6,6 +6,8 @@ import (
"fmt" "fmt"
) )
const SourceNameInline = "org.osbuild.inline"
type InlineSource struct { type InlineSource struct {
Items map[string]InlineSourceItem `json:"items"` Items map[string]InlineSourceItem `json:"items"`
} }

View file

@ -0,0 +1,128 @@
package osbuild
import (
"fmt"
"github.com/osbuild/images/pkg/rpmmd"
)
const SourceNameLibrepo = "org.osbuild.librepo"
// LibrepoSource wraps the org.osbuild.librepo osbuild source
type LibrepoSource struct {
Items map[string]*LibrepoSourceItem `json:"items"`
Options *LibrepoSourceOptions `json:"options"`
}
func NewLibrepoSource() *LibrepoSource {
return &LibrepoSource{
Items: make(map[string]*LibrepoSourceItem),
Options: &LibrepoSourceOptions{
Mirrors: make(map[string]*LibrepoSourceMirror),
},
}
}
// AddPackage adds the given *depsolved* pkg to the downloading. It
// needs the *depsovled* repoConfig so that the repoID of the two can
// be matched up
func (source *LibrepoSource) AddPackage(pkg rpmmd.PackageSpec, repos []rpmmd.RepoConfig) error {
pkgRepo, err := findRepoById(repos, pkg.RepoID)
if err != nil {
return fmt.Errorf("cannot find repo-id for pkg %v: %v", pkg.Name, err)
}
if _, ok := source.Options.Mirrors[pkgRepo.Id]; !ok {
mirror, err := mirrorFromRepo(pkgRepo)
if err != nil {
return err
}
source.Options.Mirrors[pkgRepo.Id] = mirror
}
mirror := source.Options.Mirrors[pkgRepo.Id]
if pkg.IgnoreSSL {
mirror.Insecure = true
}
// this should never happen but we should still check to avoid
// potential security issues
if mirror.Insecure && !pkg.IgnoreSSL {
return fmt.Errorf("inconsistent SSL configuration: package %v requires SSL but mirror %v is configured to ignore SSL", pkg.Name, mirror.URL)
}
if pkg.Secrets == "org.osbuild.rhsm" {
mirror.Secrets = &URLSecrets{
Name: "org.osbuild.rhsm",
}
} else if pkg.Secrets == "org.osbuild.mtls" {
mirror.Secrets = &URLSecrets{
Name: "org.osbuild.mtls",
}
}
item := &LibrepoSourceItem{
Path: pkg.Path,
MirrorID: pkgRepo.Id,
}
source.Items[pkg.Checksum] = item
return nil
}
func (LibrepoSource) isSource() {}
type LibrepoSourceItem struct {
Path string `json:"path"`
MirrorID string `json:"mirror"`
}
func findRepoById(repos []rpmmd.RepoConfig, repoID string) (*rpmmd.RepoConfig, error) {
type info struct {
ID string
Name string
}
var repoInfo []info
for _, repo := range repos {
repoInfo = append(repoInfo, info{repo.Id, repo.Name})
if repo.Id == repoID {
return &repo, nil
}
}
return nil, fmt.Errorf("cannot find repo-id %v in %+v", repoID, repoInfo)
}
func mirrorFromRepo(repo *rpmmd.RepoConfig) (*LibrepoSourceMirror, error) {
switch {
case repo.Metalink != "":
return &LibrepoSourceMirror{
URL: repo.Metalink,
Type: "metalink",
}, nil
case repo.MirrorList != "":
return &LibrepoSourceMirror{
URL: repo.MirrorList,
Type: "mirrorlist",
}, nil
case len(repo.BaseURLs) > 0:
return &LibrepoSourceMirror{
// XXX: should we pick a random one instead?
URL: repo.BaseURLs[0],
Type: "baseurl",
}, nil
}
return nil, fmt.Errorf("cannot find metalink, mirrorlist or baseurl for %+v", repo)
}
// librepoSourceOptions are the JSON options for source org.osbuild.librepo
type LibrepoSourceOptions struct {
Mirrors map[string]*LibrepoSourceMirror `json:"mirrors"`
}
type LibrepoSourceMirror struct {
URL string `json:"url"`
Type string `json:"type"`
Insecure bool `json:"insecure,omitempty"`
Secrets *URLSecrets `json:"secrets,omitempty"`
MaxParallels *int `json:"max-parallels,omitempty"`
FastestMirror bool `json:"fastest-mirror,omitempty"`
}

View file

@ -2,6 +2,8 @@ package osbuild
import "github.com/osbuild/images/pkg/ostree" import "github.com/osbuild/images/pkg/ostree"
const SourceNameOstree = "org.osbuild.ostree"
// The commits to fetch indexed their checksum // The commits to fetch indexed their checksum
type OSTreeSource struct { type OSTreeSource struct {
Items map[string]OSTreeSourceItem `json:"items"` Items map[string]OSTreeSourceItem `json:"items"`

View file

@ -3,12 +3,33 @@ package osbuild
import ( import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt"
"github.com/osbuild/images/pkg/container" "github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/dnfjson"
"github.com/osbuild/images/pkg/ostree" "github.com/osbuild/images/pkg/ostree"
"github.com/osbuild/images/pkg/rpmmd" "github.com/osbuild/images/pkg/rpmmd"
) )
// RpmDownloader specifies what backend to use for rpm downloads
// Note that the librepo backend requires a newer osbuild.
type RpmDownloader uint64
const (
RpmDownloaderCurl = iota
RpmDownloaderLibrepo = iota
)
// SourceInputs contains the inputs to generate osbuild.Sources
// Note that for Packages/RpmRepos the depsolve resolved results
// must be passed
type SourceInputs struct {
Depsolved dnfjson.DepsolveResult
Containers []container.Spec
Commits []ostree.CommitSpec
InlineData []string
}
// A Sources map contains all the sources made available to an osbuild run // A Sources map contains all the sources made available to an osbuild run
type Sources map[string]Source type Sources map[string]Source
@ -35,11 +56,13 @@ func (sources *Sources) UnmarshalJSON(data []byte) error {
for name, rawSource := range rawSources { for name, rawSource := range rawSources {
var source Source var source Source
switch name { switch name {
case "org.osbuild.curl": case SourceNameCurl:
source = new(CurlSource) source = new(CurlSource)
case "org.osbuild.inline": case SourceNameLibrepo:
source = new(LibrepoSource)
case SourceNameInline:
source = new(InlineSource) source = new(InlineSource)
case "org.osbuild.ostree": case SourceNameOstree:
source = new(OSTreeSource) source = new(OSTreeSource)
default: default:
return errors.New("unexpected source name: " + name) return errors.New("unexpected source name: " + name)
@ -54,48 +77,78 @@ func (sources *Sources) UnmarshalJSON(data []byte) error {
return nil return nil
} }
func GenSources(packages []rpmmd.PackageSpec, ostreeCommits []ostree.CommitSpec, inlineData []string, containers []container.Spec) (Sources, error) { func (sources Sources) addPackagesCurl(packages []rpmmd.PackageSpec) error {
curl := NewCurlSource()
for _, pkg := range packages {
err := curl.AddPackage(pkg)
if err != nil {
return err
}
}
sources[SourceNameCurl] = curl
return nil
}
func (sources Sources) addPackagesLibrepo(packages []rpmmd.PackageSpec, rpmRepos []rpmmd.RepoConfig) error {
librepo := NewLibrepoSource()
for _, pkg := range packages {
err := librepo.AddPackage(pkg, rpmRepos)
if err != nil {
return err
}
}
sources[SourceNameLibrepo] = librepo
return nil
}
// GenSources generates the Sources from the given inputs. Note that
// the packages and rpmRepos need to come from the *resolved* set.
func GenSources(inputs SourceInputs, rpmDownloader RpmDownloader) (Sources, error) {
sources := Sources{} sources := Sources{}
// collect rpm package sources // collect rpm package sources
if len(packages) > 0 { if len(inputs.Depsolved.Packages) > 0 {
curl := NewCurlSource() var err error
for _, pkg := range packages { switch rpmDownloader {
err := curl.AddPackage(pkg) case RpmDownloaderCurl:
if err != nil { err = sources.addPackagesCurl(inputs.Depsolved.Packages)
return nil, err case RpmDownloaderLibrepo:
} err = sources.addPackagesLibrepo(inputs.Depsolved.Packages, inputs.Depsolved.Repos)
default:
err = fmt.Errorf("unknown rpm downloader %v", rpmDownloader)
}
if err != nil {
return nil, err
} }
sources["org.osbuild.curl"] = curl
} }
// collect ostree commit sources // collect ostree commit sources
if len(ostreeCommits) > 0 { if len(inputs.Commits) > 0 {
ostree := NewOSTreeSource() ostree := NewOSTreeSource()
for _, commit := range ostreeCommits { for _, commit := range inputs.Commits {
ostree.AddItem(commit) ostree.AddItem(commit)
} }
if len(ostree.Items) > 0 { if len(ostree.Items) > 0 {
sources["org.osbuild.ostree"] = ostree sources[SourceNameOstree] = ostree
} }
} }
// collect inline data sources // collect inline data sources
if len(inlineData) > 0 { if len(inputs.InlineData) > 0 {
ils := NewInlineSource() ils := NewInlineSource()
for _, data := range inlineData { for _, data := range inputs.InlineData {
ils.AddItem(data) ils.AddItem(data)
} }
sources["org.osbuild.inline"] = ils sources[SourceNameInline] = ils
} }
// collect skopeo and local container sources // collect skopeo and local container sources
if len(containers) > 0 { if len(inputs.Containers) > 0 {
skopeo := NewSkopeoSource() skopeo := NewSkopeoSource()
skopeoIndex := NewSkopeoIndexSource() skopeoIndex := NewSkopeoIndexSource()
localContainers := NewContainersStorageSource() localContainers := NewContainersStorageSource()
for _, c := range containers { for _, c := range inputs.Containers {
if c.LocalStorage { if c.LocalStorage {
localContainers.AddItem(c.ImageID) localContainers.AddItem(c.ImageID)
} else { } else {

View file

@ -165,6 +165,9 @@ type PackageSpec struct {
Secrets string `json:"secrets,omitempty"` Secrets string `json:"secrets,omitempty"`
CheckGPG bool `json:"check_gpg,omitempty"` CheckGPG bool `json:"check_gpg,omitempty"`
IgnoreSSL bool `json:"ignore_ssl,omitempty"` IgnoreSSL bool `json:"ignore_ssl,omitempty"`
Path string `json:"path,omitempty"`
RepoID string `json:"repo_id,omitempty"`
} }
type PackageSource struct { type PackageSource struct {

2
vendor/modules.txt vendored
View file

@ -1021,7 +1021,7 @@ github.com/oracle/oci-go-sdk/v54/identity
github.com/oracle/oci-go-sdk/v54/objectstorage github.com/oracle/oci-go-sdk/v54/objectstorage
github.com/oracle/oci-go-sdk/v54/objectstorage/transfer github.com/oracle/oci-go-sdk/v54/objectstorage/transfer
github.com/oracle/oci-go-sdk/v54/workrequests github.com/oracle/oci-go-sdk/v54/workrequests
# github.com/osbuild/images v0.109.0 # github.com/osbuild/images v0.111.0
## explicit; go 1.21.0 ## explicit; go 1.21.0
github.com/osbuild/images/internal/common github.com/osbuild/images/internal/common
github.com/osbuild/images/internal/environment github.com/osbuild/images/internal/environment