From 4f9f16e07ac5691cb9d2ce3cdc96ed1cbd4a6d4b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 29 Apr 2024 11:19:14 +0200 Subject: [PATCH] manifest: ensure /var/roothome is available when needed Currently creating a customization for the root user does not work because `/var/roothome` may not be avaialble in the image. This commit ensures it is created if needed just like we do for `/var/home`. Closes https://github.com/osbuild/bootc-image-builder/issues/143 --- pkg/manifest/raw_bootc.go | 45 ++++++++++++++++++++++++++++------ pkg/manifest/raw_bootc_test.go | 41 +++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/pkg/manifest/raw_bootc.go b/pkg/manifest/raw_bootc.go index aef78642aa..00245fca9f 100644 --- a/pkg/manifest/raw_bootc.go +++ b/pkg/manifest/raw_bootc.go @@ -85,6 +85,39 @@ func (p *RawBootcImage) serializeEnd() { p.containerSpecs = nil } +func buildHomedirPaths(users []users.User) []osbuild.MkdirStagePath { + var containsRootUser, containsNormalUser bool + + for _, user := range users { + if user.Name == "root" { + containsRootUser = true + } else { + containsNormalUser = true + } + } + + rootHomePath := osbuild.MkdirStagePath{ + Path: "/var/roothome", + Mode: common.ToPtr(os.FileMode(0700)), + ExistOk: true, + } + userHomePath := osbuild.MkdirStagePath{ + Path: "/var/home", + Mode: common.ToPtr(os.FileMode(0755)), + ExistOk: true, + } + switch { + case containsRootUser && containsNormalUser: + return []osbuild.MkdirStagePath{rootHomePath, userHomePath} + case containsRootUser: + return []osbuild.MkdirStagePath{rootHomePath} + case containsNormalUser: + return []osbuild.MkdirStagePath{userHomePath} + default: + return nil + } +} + func (p *RawBootcImage) serialize() osbuild.Pipeline { pipeline := p.Base.serialize() @@ -148,16 +181,12 @@ func (p *RawBootcImage) serialize() osbuild.Pipeline { groupsStage.Devices = devices pipeline.AddStage(groupsStage) } + if len(p.Users) > 0 { - // ensure /var/home is available + // ensure home root dir (currently /var/home, /var/roothome) is + // available mkdirStage := osbuild.NewMkdirStage(&osbuild.MkdirStageOptions{ - Paths: []osbuild.MkdirStagePath{ - { - Path: "/var/home", - Mode: common.ToPtr(os.FileMode(0755)), - ExistOk: true, - }, - }, + Paths: buildHomedirPaths(p.Users), }) mkdirStage.Mounts = mounts mkdirStage.Devices = devices diff --git a/pkg/manifest/raw_bootc_test.go b/pkg/manifest/raw_bootc_test.go index 49a8792aa3..95a7074936 100644 --- a/pkg/manifest/raw_bootc_test.go +++ b/pkg/manifest/raw_bootc_test.go @@ -1,6 +1,7 @@ package manifest_test import ( + "os" "testing" "github.com/stretchr/testify/assert" @@ -132,6 +133,46 @@ func TestRawBootcImageSerializeCreateUsersOptions(t *testing.T) { } } +func TestRawBootcImageSerializeMkdirOptions(t *testing.T) { + rawBootcPipeline := makeFakeRawBootcPipeline() + + for _, tc := range []struct { + users []users.User + expectedMkdirPaths []osbuild.MkdirStagePath + }{ + {nil, nil}, + { + []users.User{{Name: "root"}}, []osbuild.MkdirStagePath{ + {Path: "/var/roothome", Mode: common.ToPtr(os.FileMode(0700)), ExistOk: true}, + }, + }, + { + []users.User{{Name: "foo"}}, []osbuild.MkdirStagePath{ + {Path: "/var/home", Mode: common.ToPtr(os.FileMode(0755)), ExistOk: true}, + }, + }, + { + []users.User{{Name: "root"}, {Name: "foo"}}, []osbuild.MkdirStagePath{ + {Path: "/var/roothome", Mode: common.ToPtr(os.FileMode(0700)), ExistOk: true}, + {Path: "/var/home", Mode: common.ToPtr(os.FileMode(0755)), ExistOk: true}, + }, + }, + } { + rawBootcPipeline.Users = tc.users + + pipeline := rawBootcPipeline.Serialize() + mkdirStage := manifest.FindStage("org.osbuild.mkdir", pipeline.Stages) + if len(tc.expectedMkdirPaths) > 0 { + // ensure options got passed + require.NotNil(t, mkdirStage) + mkdirOptions := mkdirStage.Options.(*osbuild.MkdirStageOptions) + assert.Equal(t, tc.expectedMkdirPaths, mkdirOptions.Paths) + } else { + require.Nil(t, mkdirStage) + } + } +} + func TestRawBootcImageSerializeCreateGroupOptions(t *testing.T) { rawBootcPipeline := makeFakeRawBootcPipeline()