From d4db9a5c76ae83e23146cb079a526cf2df0815c9 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 31 Jul 2025 11:26:20 +0200 Subject: [PATCH] distro: add support for filesystem from default_fs_type When we move to bootc we need a way to declare that certain partitions use the distribution default filesystem as the partition table itself is generic. This commit adds support in the YAML to omit the filesystem type, i.e. to just write: ```yaml partition_table: test_arch: partitions: - payload_type: filesystem payload: mountpoint: "/" ``` which will then translated at YAML load time to the default filesystem declared by the distribution. This allows us to write a generic YAML based partition table in images that is the same as the partition table in bootc-image-builder. --- pkg/distro/defs/loader.go | 42 ++++++++++++ pkg/distro/defs/loader_test.go | 121 +++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) diff --git a/pkg/distro/defs/loader.go b/pkg/distro/defs/loader.go index af14457b25..c56bec0b4e 100644 --- a/pkg/distro/defs/loader.go +++ b/pkg/distro/defs/loader.go @@ -240,6 +240,10 @@ func NewDistroYAML(nameVer string) (*DistroYAML, error) { if err := v.runTemplates(foundDistro); err != nil { return nil, err } + if err := v.setupDefaultFS(foundDistro.DefaultFSType.String()); err != nil { + return nil, err + } + foundDistro.imageTypes[name] = v } } @@ -462,6 +466,44 @@ func (it *ImageTypeYAML) runTemplates(distro *DistroYAML) error { return nil } +func (it *ImageTypeYAML) setupDefaultFS(distroDefaultFS string) error { + subs := func(pts map[string]*disk.PartitionTable) error { + for _, pt := range pts { + err := pt.ForEachMountable(func(mnt disk.Mountable, _ []disk.Entity) error { + elem, ok := mnt.(*disk.Filesystem) + if !ok { + return nil + } + if elem.Type == "" { + if distroDefaultFS == "" { + return fmt.Errorf("mount %q requires a default filesystem for the distribution but none set", mnt.GetMountpoint()) + } + elem.Type = distroDefaultFS + } + return nil + }) + if err != nil { + return err + } + } + return nil + } + // we need to update both the partition tables and all + // partition tables overrides + if err := subs(it.PartitionTables); err != nil { + return err + } + if it.PartitionTablesOverrides != nil { + for _, cond := range it.PartitionTablesOverrides.Conditions { + if err := subs(cond.Override); err != nil { + return err + } + } + } + + return nil +} + type platformsOverride struct { Conditions map[string]*conditionsPlatforms `yaml:"conditions,omitempty"` } diff --git a/pkg/distro/defs/loader_test.go b/pkg/distro/defs/loader_test.go index 10c1c6b24d..f6f50e681e 100644 --- a/pkg/distro/defs/loader_test.go +++ b/pkg/distro/defs/loader_test.go @@ -315,6 +315,127 @@ image_types: }, partTable) } +func TestDefsPartitionTableFilesystemDistroDefault(t *testing.T) { + fakeDistrosYaml := ` +distros: + - name: test-distro-1 + defs_path: test-distro + default_fs_type: ext4 +` + fakeImageTypesYaml := ` +image_types: + test_type: + filename: test.img + platforms: + - arch: x86_64 + partition_table: + test_arch: + partitions: + - payload_type: filesystem + payload: + # note that no "type: " is set here + mountpoint: "/" +` + baseDir := makeFakeDistrosYAML(t, fakeDistrosYaml, fakeImageTypesYaml) + restore := defs.MockDataFS(baseDir) + defer restore() + td, err := defs.NewDistroYAML("test-distro-1") + require.NoError(t, err) + it := td.ImageTypes()["test_type"] + require.NotNil(t, it) + + partTable, err := it.PartitionTable(distro.ID{Name: "test-distro", MajorVersion: 1}, "test_arch") + require.NoError(t, err) + assert.Equal(t, &disk.PartitionTable{ + Partitions: []disk.Partition{ + { + Payload: &disk.Filesystem{ + Type: "ext4", + Mountpoint: "/", + }, + }, + }, + }, partTable) +} + +func TestDefsPartitionTableFilesystemPartTableOverride(t *testing.T) { + fakeDistrosYaml := ` +distros: + - name: test-distro-1 + defs_path: test-distro + default_fs_type: ext4 +` + fakeImageTypesYaml := ` +image_types: + test_type: + filename: test.img + platforms: + - arch: x86_64 + partition_table: + x86_64: + partitions: + partition_tables_override: + conditions: + "test condition": + when: + distro_name: test-distro + override: + x86_64: + partitions: + - payload_type: filesystem + payload: + # note that no "type: " is set here + mountpoint: "/" +` + baseDir := makeFakeDistrosYAML(t, fakeDistrosYaml, fakeImageTypesYaml) + restore := defs.MockDataFS(baseDir) + defer restore() + td, err := defs.NewDistroYAML("test-distro-1") + require.NoError(t, err) + it := td.ImageTypes()["test_type"] + require.NotNil(t, it) + + partTable, err := it.PartitionTable(distro.ID{Name: "test-distro", MajorVersion: 1}, "x86_64") + require.NoError(t, err) + assert.Equal(t, &disk.PartitionTable{ + Partitions: []disk.Partition{ + { + Payload: &disk.Filesystem{ + Type: "ext4", + Mountpoint: "/", + }, + }, + }, + }, partTable) +} + +func TestDefsPartitionTableFilesystemDistroDefaultErr(t *testing.T) { + fakeDistrosYaml := ` +distros: + - name: test-distro-1 + defs_path: test-distro +` + fakeImageTypesYaml := ` +image_types: + test_type: + filename: test.img + platforms: + - arch: x86_64 + partition_table: + test_arch: + partitions: + - payload_type: filesystem + payload: + # note that no "type: " is set here + mountpoint: "/" +` + baseDir := makeFakeDistrosYAML(t, fakeDistrosYaml, fakeImageTypesYaml) + restore := defs.MockDataFS(baseDir) + defer restore() + _, err := defs.NewDistroYAML("test-distro-1") + assert.EqualError(t, err, `mount "/" requires a default filesystem for the distribution but none set`) +} + var fakeImageTypesYaml = ` image_types: test_type: