Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions cmd/image-builder/bib_legacy.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func manifestForLegacyISO(imgref, buildImgref, rootFs, rpmCacheRoot string, conf
baseCnt = container
buildCnt = container

sourceinfo, err = osinfo.Load(container.Root())
sourceinfo, err = osinfo.Load(container.RootFS())
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -111,11 +111,11 @@ func manifestForLegacyISO(imgref, buildImgref, rootFs, rpmCacheRoot string, conf
}
}()

sourceinfo, err = osinfo.Load(baseCnt.Root())
sourceinfo, err = osinfo.Load(baseCnt.RootFS())
if err != nil {
return nil, nil, err
}
buildSourceinfo, err = osinfo.Load(buildCnt.Root())
buildSourceinfo, err = osinfo.Load(buildCnt.RootFS())
if err != nil {
return nil, nil, err
}
Expand Down
19 changes: 19 additions & 0 deletions pkg/bib/blueprintload/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"

Expand Down Expand Up @@ -103,6 +104,24 @@ func Load(path string) (*blueprint.Blueprint, error) {
return loadConfig(path)
}

// LoadFS loads the blueprint at path from the given fs.FS, it auto
// detects if the blueprint is in json/toml based on the filename.
func LoadFS(fsys fs.FS, path string) (*blueprint.Blueprint, error) {
data, err := fs.ReadFile(fsys, path)
if err != nil {
return nil, err
}

switch filepath.Ext(path) {
case ".json":
return decodeJsonBuildConfig(bytes.NewReader(data), path)
case ".toml":
return decodeTomlBuildConfig(bytes.NewReader(data), path)
default:
return nil, fmt.Errorf("unsupported file extension for %q", path)
}
}

func readWithFallback(userConfig string) (*blueprint.Blueprint, error) {
// user asked for an explicit config
if userConfig != "" {
Expand Down
58 changes: 29 additions & 29 deletions pkg/bib/osinfo/osinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"bufio"
"errors"
"fmt"
"io/fs"
"os"
"path"
"path/filepath"
"slices"
"strings"

Expand Down Expand Up @@ -112,19 +112,19 @@ func validateOSRelease(osrelease map[string]string) error {
return nil
}

func uefiVendor(root string) (string, error) {
func uefiVendor(fsys fs.FS) (string, error) {
var searchPath = []string{
"usr/lib/bootupd/updates/EFI/*",
"usr/lib/efi/shim/*/EFI/*",
}
for _, baseDir := range searchPath {
dents, err := filepath.Glob(filepath.Join(root, baseDir))
dents, err := fs.Glob(fsys, baseDir)
if err != nil {
return "", err
}
// best-effort search: return the first directory that's not "BOOT"
for _, p := range dents {
entry, err := os.Stat(p)
entry, err := fs.Stat(fsys, p)
if err != nil {
return "", err
}
Expand All @@ -141,9 +141,9 @@ func uefiVendor(root string) (string, error) {
return "", fmt.Errorf("cannot find UEFI vendor in %s", searchPath)
}

func readSelinuxPolicy(root string) (string, error) {
func readSelinuxPolicy(fsys fs.FS) (string, error) {
configPath := "etc/selinux/config"
f, err := os.Open(path.Join(root, configPath))
f, err := fsys.Open(configPath)
if err != nil {
return "", fmt.Errorf("cannot read selinux config %s: %w", configPath, err)
}
Expand Down Expand Up @@ -174,18 +174,18 @@ func readSelinuxPolicy(root string) (string, error) {
return policy, nil
}

func readImageCustomization(root string) (*blueprint.Customizations, error) {
func readImageCustomization(fsys fs.FS) (*blueprint.Customizations, error) {
// note that we only look at the 'old' search path here, we do want to
// look in the new path as well but i'd like to only support the actual
// blueprint format there instead of buildconfig as well
prefix := path.Join(root, searchPaths[1])
prefix := searchPaths[1]

config, err := blueprintload.Load(path.Join(prefix, "config.json"))
config, err := blueprintload.LoadFS(fsys, path.Join(prefix, "config.json"))
if err != nil && !os.IsNotExist(err) {
return nil, err
}
if config == nil {
config, err = blueprintload.Load(path.Join(prefix, "config.toml"))
config, err = blueprintload.LoadFS(fsys, path.Join(prefix, "config.toml"))
if err != nil && !os.IsNotExist(err) {
return nil, err
}
Expand All @@ -203,11 +203,11 @@ type diskYAML struct {
PartitionTable *disk.PartitionTable `json:"partition_table" yaml:"partition_table"`
}

func readDiskYaml(root string) (*diskYAML, error) {
func readDiskYaml(fsys fs.FS) (*diskYAML, error) {
for _, prefixPath := range searchPaths {
var disk diskYAML
p := path.Join(root, prefixPath, "disk.yaml")
f, err := os.Open(p)
p := path.Join(prefixPath, "disk.yaml")
f, err := fsys.Open(p)
if err != nil {
if os.IsNotExist(err) {
continue
Expand Down Expand Up @@ -240,11 +240,11 @@ type isoYAML struct {
} `json:"grub2" yaml:"grub2"`
}

func readISOYaml(root string) (*isoYAML, error) {
func readISOYaml(fsys fs.FS) (*isoYAML, error) {
for _, prefixPath := range searchPaths {
var iso isoYAML
p := path.Join(root, prefixPath, "iso.yaml")
f, err := os.Open(p)
p := path.Join(prefixPath, "iso.yaml")
f, err := fsys.Open(p)
if err != nil {
if os.IsNotExist(err) {
continue
Expand All @@ -263,9 +263,9 @@ func readISOYaml(root string) (*isoYAML, error) {
return nil, nil
}

func readKernelInfo(root string) (*KernelInfo, error) {
modulesDir := path.Join(root, "usr/lib/modules")
entries, err := os.ReadDir(modulesDir)
func readKernelInfo(fsys fs.FS) (*KernelInfo, error) {
modulesDir := "usr/lib/modules"
entries, err := fs.ReadDir(fsys, modulesDir)
if err != nil {
return nil, err
}
Expand All @@ -280,11 +280,11 @@ func readKernelInfo(root string) (*KernelInfo, error) {
// pick the first here
kernelDir := path.Join(modulesDir, e.Name())
kernelPath := path.Join(kernelDir, "vmlinuz")
_, err := os.Stat(kernelPath)
_, err := fs.Stat(fsys, kernelPath)
if err == nil {

abootPath := path.Join(kernelDir, "aboot.img")
_, err := os.Stat(abootPath)
_, err := fs.Stat(fsys, abootPath)
hasAbootImg := err == nil
return &KernelInfo{
Version: e.Name(),
Expand All @@ -296,26 +296,26 @@ func readKernelInfo(root string) (*KernelInfo, error) {
return nil, fmt.Errorf("no valid kernel modules directory")
}

func Load(root string) (*Info, error) {
osrelease, err := distro.ReadOSReleaseFromTree(root)
func Load(fsys fs.FS) (*Info, error) {
osrelease, err := distro.ReadOSReleaseFromFS(fsys)
if err != nil {
return nil, err
}
if err := validateOSRelease(osrelease); err != nil {
return nil, err
}

vendor, err := uefiVendor(root)
vendor, err := uefiVendor(fsys)
if err != nil {
olog.Printf("cannot read UEFI vendor: %v, setting it to none", err)
}

customization, err := readImageCustomization(root)
customization, err := readImageCustomization(fsys)
if err != nil {
return nil, err
}

diskYaml, err := readDiskYaml(root)
diskYaml, err := readDiskYaml(fsys)
if err != nil {
return nil, err
}
Expand All @@ -326,7 +326,7 @@ func Load(root string) (*Info, error) {
pt = diskYaml.PartitionTable
}

isoYaml, err := readISOYaml(root)
isoYaml, err := readISOYaml(fsys)
if err != nil {
return nil, err
}
Expand All @@ -348,12 +348,12 @@ func Load(root string) (*Info, error) {
}
}

kernelInfo, err := readKernelInfo(root)
kernelInfo, err := readKernelInfo(fsys)
if err != nil {
olog.Printf("cannot read kernel info: %v", err)
}

selinuxPolicy, err := readSelinuxPolicy(root)
selinuxPolicy, err := readSelinuxPolicy(fsys)
if err != nil {
olog.Printf("cannot read selinux policy: %v, setting it to none", err)
}
Expand Down
20 changes: 10 additions & 10 deletions pkg/bib/osinfo/osinfo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func TestLoadInfo(t *testing.T) {
{"sad-no-id", "", "40", "Fedora Linux", "fedora", "platform:f40", "", "", "json", "missing ID in os-release"},
{"sad-no-id", "fedora", "", "Fedora Linux", "fedora", "platform:f40", "", "", "json", "missing VERSION_ID in os-release"},
{"sad-no-id", "fedora", "40", "", "fedora", "platform:f40", "", "", "json", "missing NAME in os-release"},
{"sad-broken-json", "fedora", "40", "Fedora Linux", "fedora", "platform:f40", "coreos", "", "broken", "cannot decode \"$ROOT/usr/lib/bootc-image-builder/config.json\": unexpected EOF"},
{"sad-broken-json", "fedora", "40", "Fedora Linux", "fedora", "platform:f40", "coreos", "", "broken", "cannot decode \"usr/lib/bootc-image-builder/config.json\": unexpected EOF"},
}

for _, c := range cases {
Expand All @@ -139,7 +139,7 @@ func TestLoadInfo(t *testing.T) {

}

info, err := Load(root)
info, err := Load(os.DirFS(root))

if c.errorStr != "" {
require.EqualError(t, err, strings.ReplaceAll(c.errorStr, "$ROOT", root))
Expand Down Expand Up @@ -207,7 +207,7 @@ func TestLoadInfoKernel(t *testing.T) {
filePath := path.Join(baseDir, file)
require.NoError(t, os.WriteFile(filePath, nil, 0644))
}
info, err := readKernelInfo(root)
info, err := readKernelInfo(os.DirFS(root))
if c.expected == nil {
require.Error(t, err)
assert.Nil(t, info)
Expand Down Expand Up @@ -256,7 +256,7 @@ func TestLoadInfoPartitionTableHappy(t *testing.T) {
writeOSRelease(t, root, "fedora", "40", "Fedora Linux", "fedora", "platform:f40", "coreos")
createPartitionTable(t, root, fakePartitionTableYAML, dest)

info, err := Load(root)
info, err := Load(os.DirFS(root))
require.NoError(t, err)
assert.Equal(t, &disk.PartitionTable{
Type: disk.PT_GPT,
Expand All @@ -277,8 +277,8 @@ func TestLoadInfoPartitionTableSad(t *testing.T) {
writeOSRelease(t, root, "fedora", "40", "Fedora Linux", "fedora", "platform:f40", "coreos")
createPartitionTable(t, root, "@invalidYAML", "/usr/lib/bootc-image-builder/disk.yaml")

_, err := Load(root)
assert.EqualError(t, err, fmt.Sprintf(`cannot parse disk definitions from "%s/usr/lib/bootc-image-builder/disk.yaml": yaml: found character that cannot start any token`, root))
_, err := Load(os.DirFS(root))
assert.EqualError(t, err, `cannot parse disk definitions from "usr/lib/bootc-image-builder/disk.yaml": yaml: found character that cannot start any token`)
}

var fakeISOYAML = `
Expand Down Expand Up @@ -319,7 +319,7 @@ func TestLoadInfoISOHappy(t *testing.T) {
writeOSRelease(t, root, "fedora", "40", "Fedora Linux", "fedora", "platform:f40", "coreos")
createISO(t, root, fakeISOYAML, dest)

info, err := Load(root)
info, err := Load(os.DirFS(root))
require.NoError(t, err)

assert.Equal(t, "My-ISO", info.ISOInfo.Label)
Expand All @@ -345,8 +345,8 @@ func TestLoadInfoISOSad(t *testing.T) {
writeOSRelease(t, root, "fedora", "40", "Fedora Linux", "fedora", "platform:f40", "coreos")
createISO(t, root, "@invalidYAML", "/usr/lib/bootc-image-builder/iso.yaml")

_, err := Load(root)
assert.EqualError(t, err, fmt.Sprintf(`cannot parse iso definitions from "%s/usr/lib/bootc-image-builder/iso.yaml": yaml: found character that cannot start any token`, root))
_, err := Load(os.DirFS(root))
assert.EqualError(t, err, `cannot parse iso definitions from "usr/lib/bootc-image-builder/iso.yaml": yaml: found character that cannot start any token`)
}

func TestLoadInfoUEFIVendorSearchPath(t *testing.T) {
Expand All @@ -356,7 +356,7 @@ func TestLoadInfoUEFIVendorSearchPath(t *testing.T) {
err := os.MkdirAll(path.Join(root, "usr/lib/efi/shim/1.64/EFI/fedora"), 0755)
assert.NoError(t, err)

info, err := Load(root)
info, err := Load(os.DirFS(root))
assert.NoError(t, err)
assert.Equal(t, "fedora", info.UEFIVendor)
}
Expand Down
Loading
Loading