Skip to content

Commit

Permalink
image,manifest: allow using the qcow2 pipeline without a build pipeline
Browse files Browse the repository at this point in the history
This commit allows to use the qcow2 pipeline outside of a build
pipeline. The use-case is the `bootc-image-builder` that will use
arbitrary containers as buildroots and we cannot assume that they
have `qemu-util` installed. And because `bootc-image-builder` is
already a container we can install `qemu-util` there and be
confident that it will work.
  • Loading branch information
mvo5 authored and achilleas-k committed Jan 17, 2024
1 parent 32e6676 commit eb24e7e
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 5 deletions.
5 changes: 2 additions & 3 deletions pkg/image/bootc_disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,8 @@ func (img *BootcDiskImage) InstantiateManifestFromContainers(m *manifest.Manifes
baseImage := baseRawOstreeImage(img.OSTreeDiskImage, buildPipeline)
switch imgFormat {
case platform.FORMAT_QCOW2:
// TODO: create new build pipeline here that uses "bib" itself
// as the buildroot to get access to tooling like "qemu-img"
qcow2Pipeline := manifest.NewQCOW2(buildPipeline, baseImage)
// qcow2 runs without a build pipeline directly from "bib"
qcow2Pipeline := manifest.NewQCOW2(nil, baseImage)
qcow2Pipeline.Compat = img.Platform.GetQCOW2Compat()
qcow2Pipeline.SetFilename(img.Filename)
return qcow2Pipeline.Export(), nil
Expand Down
79 changes: 79 additions & 0 deletions pkg/image/bootc_disk_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package image_test

import (
"encoding/hex"
"encoding/json"
"math/rand"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/osbuild/images/pkg/container"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/image"
"github.com/osbuild/images/pkg/manifest"
"github.com/osbuild/images/pkg/platform"
"github.com/osbuild/images/pkg/runner"
)

func TestBootcDiskImageNew(t *testing.T) {
Expand All @@ -20,3 +27,75 @@ func TestBootcDiskImageNew(t *testing.T) {
require.NotNil(t, img)
assert.Equal(t, img.OSTreeDiskImage.Base.Name(), "bootc-raw-image")
}

func makeFakeDigest(t *testing.T) string {
data := make([]byte, 32)
_, err := rand.Read(data) // nolint:gosec
require.Nil(t, err)
return "sha256:" + hex.EncodeToString(data[:])
}

func makeFakePlatform() platform.Platform {
return &platform.X86{
BasePlatform: platform.BasePlatform{
ImageFormat: platform.FORMAT_QCOW2,
},
}
}

func makeFakePartitionTable() *disk.PartitionTable {
return &disk.PartitionTable{
Type: "gpt",
Partitions: []disk.Partition{
{
Payload: &disk.Filesystem{
Type: "ext4",
UUID: disk.RootPartitionUUID,
Mountpoint: "/",
},
},
},
}
}

func TestBootcDiskImageInstantiateNoBuildpipelineForQcow2(t *testing.T) {
containerSource := container.SourceSpec{
Source: "some-src",
Name: "name",
}
containers := []container.SourceSpec{containerSource}

img := image.NewBootcDiskImage(containerSource)
require.NotNil(t, img)
img.Platform = makeFakePlatform()
img.PartitionTable = makeFakePartitionTable()

m := &manifest.Manifest{}
runi := &runner.Fedora{}
_, err := img.InstantiateManifestFromContainers(m, containers, runi, nil)
require.Nil(t, err)
sourceSpecs := map[string][]container.Spec{
"build": []container.Spec{{Source: "some-src", Digest: makeFakeDigest(t), ImageID: makeFakeDigest(t)}},
"ostree-deployment": []container.Spec{{Source: "other-src", Digest: makeFakeDigest(t), ImageID: makeFakeDigest(t)}},
}
osbuildManifest, err := m.Serialize(nil, sourceSpecs, nil)
require.Nil(t, err)

var mani map[string]interface{}
err = json.Unmarshal(osbuildManifest, &mani)
require.Nil(t, err)
pipelines := mani["pipelines"].([]interface{})
findQcowStage := func() map[string]interface{} {
for _, stageIf := range pipelines {
stage := stageIf.(map[string]interface{})
if stage["name"].(string) == "qcow2" {
return stage
}
}
return nil
}
qcowStage := findQcowStage()
require.NotNil(t, qcowStage)
// no build pipeline for qcow2
assert.Equal(t, qcowStage["build"], nil)
}
2 changes: 1 addition & 1 deletion pkg/manifest/ostree_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ func (p *OSTreeDeployment) serializeStart(packages []rpmmd.PackageSpec, containe
case len(containers) == 1:
p.containerSpec = &containers[0]
default:
panic(fmt.Sprintf("pipeline requires exactly one ostree commit or one container (have commits: %v; containers: %v)", commits, containers))
panic(fmt.Sprintf("pipeline %s requires exactly one ostree commit or one container (have commits: %v; containers: %v)", p.Name(), commits, containers))
}
}

Expand Down
7 changes: 6 additions & 1 deletion pkg/manifest/qcow2.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,12 @@ func NewQCOW2(buildPipeline Build, imgPipeline FilePipeline) *QCOW2 {
imgPipeline: imgPipeline,
filename: "image.qcow2",
}
buildPipeline.addDependent(p)
// qcow2 can run outside the build pipeline for e.g. "bib"
if buildPipeline != nil {
buildPipeline.addDependent(p)
} else {
imgPipeline.Manifest().addPipeline(p)
}
return p
}

Expand Down

0 comments on commit eb24e7e

Please sign in to comment.