debian-forge-cli/cmd/image-builder/describeimg.go
Tomáš Hozza 49c87afb33 cmd/describe: fix describing of '*-simplified-installer' images
The  '*-simplified-installer' images require the installation device
to be specified as a BP customization to serialize their Manifest.
The 'describe' command was not setting those, which resulted in errors
when describing such image types.

Set a dummy installation device BP customization for image types with
their name ending with '-simplified-installer', to enable describing
of such images.

Signed-off-by: Tomáš Hozza <thozza@redhat.com>
2025-06-23 18:31:27 +00:00

136 lines
3.9 KiB
Go

package main
import (
"errors"
"fmt"
"io"
"slices"
"strings"
"gopkg.in/yaml.v3"
"github.com/osbuild/images/pkg/blueprint"
"github.com/osbuild/images/pkg/disk"
"github.com/osbuild/images/pkg/distro"
"github.com/osbuild/images/pkg/distro/defs"
"github.com/osbuild/images/pkg/imagefilter"
"github.com/osbuild/images/pkg/ostree"
)
// Use yaml output by default because it is both nicely human and
// machine readable and parts of our image defintions will be written
// in yaml too. This means this should be a possible input a
// "flattended" image definiton.
type describeImgYAML struct {
Distro string `yaml:"distro"`
Type string `yaml:"type"`
Arch string `yaml:"arch"`
// XXX: think about ordering (as this is what the user will see)
OsVersion string `yaml:"os_version"`
Bootmode string `yaml:"bootmode"`
PartitionType string `yaml:"partition_type"`
DefaultFilename string `yaml:"default_filename"`
BuildPipelines []string `yaml:"build_pipelines"`
PayloadPipelines []string `yaml:"payload_pipelines"`
Packages map[string]*packagesYAML `yaml:"packages"`
PartitionTable *disk.PartitionTable `yaml:"partition_table,omitempty"`
}
type packagesYAML struct {
Include []string `yaml:"include"`
Exclude []string `yaml:"exclude"`
}
func packageSetsFor(imgType distro.ImageType) (map[string]*packagesYAML, error) {
var bp blueprint.Blueprint
// XXX: '*-simplified-installer' images require the installation device to be specified as a BP customization.
// Workaround this for now by setting a dummy device. We should ideally have a way to get image type pkg sets
// without doing this.
if strings.HasSuffix(imgType.Name(), "-simplified-installer") {
bp.Customizations = &blueprint.Customizations{
InstallationDevice: "/dev/dummy",
}
}
var imgOpts distro.ImageOptions
// Mock ostree options for ostree-based images to make describe work
if imgType.OSTreeRef() != "" {
imgOpts.OSTree = &ostree.ImageOptions{
URL: "http://example.com/repo",
}
}
manifest, _, err := imgType.Manifest(&bp, imgOpts, nil, nil)
if err != nil {
return nil, err
}
res := make(map[string]*packagesYAML)
for pipelineName, pkgSets := range manifest.GetPackageSetChains() {
incM := map[string]bool{}
excM := map[string]bool{}
for _, pkgSet := range pkgSets {
for _, s := range pkgSet.Include {
incM[s] = true
}
for _, s := range pkgSet.Exclude {
excM[s] = true
}
}
inc := make([]string, 0, len(incM))
exc := make([]string, 0, len(excM))
for name := range incM {
inc = append(inc, name)
}
for name := range excM {
exc = append(exc, name)
}
slices.Sort(inc)
slices.Sort(exc)
res[pipelineName] = &packagesYAML{
Include: inc,
Exclude: exc,
}
}
return res, nil
}
// XXX: should this live in images instead?
func describeImage(img *imagefilter.Result, out io.Writer) error {
// see
// https://github.com/osbuild/images/pull/1019#discussion_r1832376568
// for what is available on an image (without depsolve or partitioning)
pkgSets, err := packageSetsFor(img.ImgType)
if err != nil {
return err
}
partTable, err := img.ImgType.BasePartitionTable()
if err != nil && !errors.Is(err, defs.ErrNoPartitionTableForImgType) {
return err
}
outYaml := &describeImgYAML{
Distro: img.Distro.Name(),
OsVersion: img.Distro.OsVersion(),
Arch: img.Arch.Name(),
Type: img.ImgType.Name(),
Bootmode: img.ImgType.BootMode().String(),
PartitionType: img.ImgType.PartitionType().String(),
DefaultFilename: img.ImgType.Filename(),
BuildPipelines: img.ImgType.BuildPipelines(),
PayloadPipelines: img.ImgType.PayloadPipelines(),
Packages: pkgSets,
PartitionTable: partTable,
}
// deliberately break the yaml until the feature is stable
fmt.Fprint(out, "@WARNING - the output format is not stable yet and may change\n")
enc := yaml.NewEncoder(out)
enc.SetIndent(2)
return enc.Encode(outYaml)
}