From 70fce2f96f0a2b82e3595a97d2943851f33a4f54 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 9 Sep 2024 18:03:18 +0200 Subject: [PATCH] cmd: add new `otk-make-grub2-inst-stage` external This external allows us to generate the `org.osbuild.grub2.inst` for `otk`. E.g. in PR#193 we can now use the following diff: ```yaml diff --git a/example/centos/centos-9-x86_64-qcow2.yaml b/example/centos/centos-9-x86_64-qcow2.yaml index 0d6c0cd..b3693d4 100644 --- a/example/centos/centos-9-x86_64-qcow2.yaml +++ b/example/centos/centos-9-x86_64-qcow2.yaml @@ -262,20 +262,9 @@ otk.target.osbuild: ${fs_options.devices} mounts: ${fs_options.mounts} - - type: org.osbuild.grub2.inst - options: - filename: disk.img + - - otk.external.otk-make-grub2-inst-stage: platform: i386-pc - location: 2048 - core: - type: mkimage - partlabel: gpt - filesystem: xfs - prefix: - type: partition - partlabel: gpt - number: 2 - path: /grub2 + filesystem: ${filesystem} - name: qcow2 build: name:build stages: ``` --- cmd/otk-make-grub2-inst-stage/export_test.go | 3 + cmd/otk-make-grub2-inst-stage/main.go | 48 +++++++++++ cmd/otk-make-grub2-inst-stage/main_test.go | 91 ++++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 cmd/otk-make-grub2-inst-stage/export_test.go create mode 100644 cmd/otk-make-grub2-inst-stage/main.go create mode 100644 cmd/otk-make-grub2-inst-stage/main_test.go diff --git a/cmd/otk-make-grub2-inst-stage/export_test.go b/cmd/otk-make-grub2-inst-stage/export_test.go new file mode 100644 index 0000000000..cc2e2795d4 --- /dev/null +++ b/cmd/otk-make-grub2-inst-stage/export_test.go @@ -0,0 +1,3 @@ +package main + +var Run = run diff --git a/cmd/otk-make-grub2-inst-stage/main.go b/cmd/otk-make-grub2-inst-stage/main.go new file mode 100644 index 0000000000..4849030c37 --- /dev/null +++ b/cmd/otk-make-grub2-inst-stage/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "encoding/json" + "fmt" + "io" + "os" + + "github.com/osbuild/images/pkg/osbuild" + + "github.com/osbuild/images/internal/otkdisk" +) + +type Input struct { + Tree Tree `json:"tree"` +} + +type Tree struct { + Platform string `json:"platform"` + Filesystem otkdisk.Data `json:"filesystem"` +} + +func run(r io.Reader, w io.Writer) error { + var inp Input + if err := json.NewDecoder(r).Decode(&inp); err != nil { + return err + } + + opts := osbuild.NewGrub2InstStageOption(inp.Tree.Filesystem.Const.Filename, inp.Tree.Filesystem.Const.Internal.PartitionTable, inp.Tree.Platform) + stage := osbuild.NewGrub2InstStage(opts) + + out := map[string]interface{}{ + "tree": stage, + } + outputJson, err := json.MarshalIndent(out, "", " ") + if err != nil { + return fmt.Errorf("cannot marshal response: %w", err) + } + fmt.Fprintf(w, "%s\n", outputJson) + return nil +} + +func main() { + if err := run(os.Stdin, os.Stdout); err != nil { + fmt.Fprintf(os.Stderr, "error: %v", err.Error()) + os.Exit(1) + } +} diff --git a/cmd/otk-make-grub2-inst-stage/main_test.go b/cmd/otk-make-grub2-inst-stage/main_test.go new file mode 100644 index 0000000000..5a56923965 --- /dev/null +++ b/cmd/otk-make-grub2-inst-stage/main_test.go @@ -0,0 +1,91 @@ +package main_test + +import ( + "bytes" + "encoding/json" + "testing" + + "github.com/stretchr/testify/assert" + + makeGrub2Inst "github.com/osbuild/images/cmd/otk-make-grub2-inst-stage" + "github.com/osbuild/images/internal/common" + "github.com/osbuild/images/internal/otkdisk" + "github.com/osbuild/images/pkg/disk" +) + +var fakePt = &disk.PartitionTable{ + Type: "gpt", + Partitions: []disk.Partition{ + { + Size: 1 * common.MiB, + Start: 1 * common.MiB, + Bootable: true, + Type: disk.BIOSBootPartitionGUID, + UUID: disk.BIOSBootPartitionUUID, + }, + { + Size: 1 * common.GiB, + Payload: &disk.Filesystem{ + Type: "ext4", + Mountpoint: "/", + UUID: disk.RootPartitionUUID, + }, + }, + }, +} + +// this is not symetrical to the output, this is sad but also +// okay because the input is really just a dump of the internal +// disk.PartitionTable so encoding it in json here will not add +// a benefit for the test +var minimalInputBase = makeGrub2Inst.Input{ + Tree: makeGrub2Inst.Tree{ + Platform: "i386-pc", + Filesystem: otkdisk.Data{ + Const: otkdisk.Const{ + Internal: otkdisk.Internal{ + PartitionTable: fakePt, + }, + }, + }, + }, +} + +var minimalExpectedStages = `{ + "tree": { + "type": "org.osbuild.grub2.inst", + "options": { + "filename": "disk.img", + "platform": "i386-pc", + "location": 2048, + "core": { + "type": "mkimage", + "partlabel": "gpt", + "filesystem": "ext4" + }, + "prefix": { + "type": "partition", + "partlabel": "gpt", + "number": 1, + "path": "/boot/grub2" + } + } + } +} +` + +func TestIntegration(t *testing.T) { + minimalInput := minimalInputBase + minimalInput.Tree.Filesystem.Const.Filename = "disk.img" + expectedStages := minimalExpectedStages + + inpJSON, err := json.Marshal(&minimalInput) + assert.NoError(t, err) + fakeStdin := bytes.NewBuffer(inpJSON) + fakeStdout := bytes.NewBuffer(nil) + + err = makeGrub2Inst.Run(fakeStdin, fakeStdout) + assert.NoError(t, err) + + assert.Equal(t, expectedStages, fakeStdout.String()) +}