Skip to content
2 changes: 1 addition & 1 deletion data/dependencies/deps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ import (
)

func TestMinimumOSBuildVersion(t *testing.T) {
assert.Equal(t, "178", dependencies.MinimumOSBuildVersion())
assert.Equal(t, "180", dependencies.MinimumOSBuildVersion())
}
2 changes: 1 addition & 1 deletion data/dependencies/osbuild
Original file line number Diff line number Diff line change
@@ -1 +1 @@
178
180
3 changes: 3 additions & 0 deletions pkg/bootc/bootc.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ type Info struct {

// The size of the container image
Size uint64

// Is the container using a unified kernel?
UnifiedKernel bool
}
33 changes: 33 additions & 0 deletions pkg/bootc/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ func (c *Container) ResolveInfo() (*Info, error) {
}
bootcInfo.DefaultRootFs = defaultFs

unifiedKernel, err := c.UnifiedKernel()
if err != nil {
return nil, err
}
bootcInfo.UnifiedKernel = unifiedKernel

size, err := getContainerSize(c.ref, c.extraOpts)
if err != nil {
return nil, err
Expand Down Expand Up @@ -332,6 +338,33 @@ func (c *Container) InitrdModules(kver string) ([]string, error) {
return strings.Split(strings.TrimRight(string(output), "\n"), "\n"), nil
}

// UnifiedKernel finds out if the kernel inside the bootc container is unified
func (c *Container) UnifiedKernel() (bool, error) {
args := []string{"exec"}
args = append(args, c.extraOpts...)
args = append(args, c.id, "bootc", "container", "inspect", "--json")

/* #nosec G204 */
output, err := exec.Command("podman", args...).Output()
if err != nil {
return false, fmt.Errorf("failed to run bootc container inspect: %w, output:\n%s", err, output)
}

var bootcInspect struct {
Kargs []string `json:"kargs"`
Kernel struct {
Version string `json:"version"`
Unified bool `json:"unified"`
} `json:"kernel"`
Comment on lines +354 to +358
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: the kargs and version don't seem to be used anywhere or even unit-tested. I think that it is useful to unmarshal all this information while we are at it, but technically this is a dead code, because on the kernel.unified value is ever returned from this method.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea this is true; I had some plans to start using them. I'll try to do that in a follow-up. For example we have our own kernel-scanning code at the moment for the version and now that bootc can give it we might be able to move some bits around.

}

if err := json.Unmarshal(output, &bootcInspect); err != nil {
return false, fmt.Errorf("failed to unmarshal bootc inspect : %w", err)
}

return bootcInspect.Kernel.Unified, nil
}

func findImageIdFor(cntId, ref string, extraOpts []string) (string, error) {
args := []string{"inspect"}
args = append(args, extraOpts...)
Expand Down
20 changes: 20 additions & 0 deletions pkg/bootc/resolver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,3 +222,23 @@ echo '%s'
assert.ErrorContains(t, err, "unsupported root filesystem type: ext1, supported: ")
}
}

func TestUnifiedKernelHappy(t *testing.T) {
for _, tc := range []struct {
In string
Out bool
}{
{`{"kernel": {"unified": true}}`, true},
{`{"kernel": {"unified": false}}`, false},
{`{"kernel": {}}`, false},
{`{}`, false},
} {
makeFakePodman(t, fmt.Sprintf(`#!/bin/sh
echo '%s'
`, tc.In))
cnt := bootc.Container{}
unified, err := cnt.UnifiedKernel()
assert.NoError(t, err)
assert.Equal(t, tc.Out, unified)
}
}
13 changes: 8 additions & 5 deletions pkg/distro/bootc/bootctest/exe/bootc.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import (
)

func fakeBootc() error {
if os.Args[1] != "install" || os.Args[2] != "print-configuration" {
return fmt.Errorf("unexpected bootc arguments %v", os.Args)
if len(os.Args) >= 3 && os.Args[1] == "install" && os.Args[2] == "print-configuration" {
fmt.Println(`{"filesystem": {"root": {"type": "ext4"}}}`)
return nil
}
// print a sensible default configuration
fmt.Println(`{"filesystem": {"root": {"type": "ext4"}}}`)
return nil
if len(os.Args) >= 4 && os.Args[1] == "container" && os.Args[2] == "inspect" && os.Args[3] == "--json" {
fmt.Println(`{"kernel": {"unified": false}}`)
return nil
}
return fmt.Errorf("unexpected bootc arguments %v", os.Args)
}

func fakeSleep() error {
Expand Down
4 changes: 4 additions & 0 deletions pkg/osbuild/bootc_install_to_filesystem_stage.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ type BootcInstallToFilesystemOptions struct {

// option for --target-imgref
TargetImgref string `json:"target-imgref"`

Bootloader string `json:"bootloader,omitempty"`

ComposeFS *bool `json:"composefs,omitempty"`
}

func (BootcInstallToFilesystemOptions) isStageOptions() {}
Expand Down