Skip to content

feat(buildsys): embed guest variant images via build-variant guest-images#669

Open
jmt-lab wants to merge 1 commit into
bottlerocket-os:developfrom
jmt-lab:feat/images-package
Open

feat(buildsys): embed guest variant images via build-variant guest-images#669
jmt-lab wants to merge 1 commit into
bottlerocket-os:developfrom
jmt-lab:feat/images-package

Conversation

@jmt-lab

@jmt-lab jmt-lab commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Add a declarative guest-images field to a host variant's
[package.metadata.build-variant] manifest that embeds the disk-image
artifacts of one or more already-built guest variants into the host's
rootfs. This enables shipping variant-A images as content inside
variant-B (e.g. installer media, recovery partitions, AMI-bundled
secondaries) without introducing a new package type or CLI surface.

Manifest schema:

[package.metadata.build-variant.guest-images]
inner-variant = "/usr/share/bottlerocket/guests/inner"

[build-dependencies]
inner-variant = { path = "../inner-variant" }

buildsys build-variant validates each entry: the key must appear in
[build-dependencies], the target must itself be a build-variant,
the value must be an absolute install path, and a variant may not
reference itself. Validated entries are threaded through a
GUEST_IMAGES build-arg (newline-delimited
<guest>:<install_path>:build/images/<arch>-<guest>/<version>) into the
imgbuild Dockerfile stage, where rpm2img (via the new
guest-images-helper) cp -as each guest's image directory into
${ROOT_MOUNT}<install_path> after rpm -iv and before SELinux
relabel, so embedded files inherit correct labels.

Tests:

  • Unit: test_build_variant_with_guest_images,
    test_build_variant_without_guest_images,
    test_build_type_default_package_unchanged, plus
    validate_guest_image_entries and guest_image_variant_deps
    coverage for invalid names/paths, self-reference, missing build-dep,
    transitive-only build-dep, and the happy path.
  • Fixtures: tests/projects/guest-images-kit (host wrapper-variant
    embedding an inner-variant) and guest-images-graph (direct,
    transitive, and self-referential guest deps).
  • Integration (#[ignore], requires Docker):
    test_twoliter_build_variant_consumes_guest_images asserts the
    guest variant builds transitively and the host variant produces
    image artifacts.
    Terms of contribution:

By submitting this pull request, I agree that this contribution is dual-licensed under the terms of both the Apache License, version 2.0, and the MIT license.

Comment thread tools/buildsys/src/builder.rs Outdated
@jmt-lab jmt-lab force-pushed the feat/images-package branch 3 times, most recently from 980f755 to aeeac65 Compare June 5, 2026 23:13
@jmt-lab jmt-lab changed the title feat(buildsys): add build-image-package package type feat(buildsys): embed guest variant images via build-variant guest-images Jun 5, 2026
@jmt-lab jmt-lab force-pushed the feat/images-package branch from aeeac65 to f7cd97a Compare June 8, 2026 20:06
Comment thread twoliter/embedded/guest-images-helper Outdated

@arnaldo2792 arnaldo2792 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First quick pass, this is the one line I would really like to keep as downstreams requested.

Comment thread twoliter/embedded/rpm2img
Comment on lines +180 to +182
# not the build metadata that lives alongside them. Files such as `application-inventory
# .json`, `artifact-metadata.json`, `pcr-predictions.json`, and the `*-sbom-*` SBOM files
# describe the *guest* build and have no business inside the *host* rootfs; embedding them

@arnaldo2792 arnaldo2792 Jun 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PCR predictions might not, but the sboms yes. So do please include them. Ideally, the SBOM of the host should include it. Basically, treat it as another package that should appear in the host's SBOM.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jmt this comment needs updating now that guest SBOMs are included in the host

Comment thread tools/buildsys/src/manifest/error.rs Outdated
Comment thread tools/buildsys/src/manifest.rs Outdated
Comment thread twoliter/embedded/build.Dockerfile Outdated
Comment thread twoliter/embedded/build.Dockerfile Outdated
…ages

Add a declarative `guest-images` field to a host variant's
`[package.metadata.build-variant]` manifest that embeds the disk-image
artifacts of one or more already-built guest variants into the host's
rootfs. This enables shipping variant-A images as content inside
variant-B (e.g. installer media, recovery partitions, AMI-bundled
secondaries) without introducing a new package type or CLI surface.

Manifest schema:

  [package.metadata.build-variant.guest-images]
  inner-variant = "/usr/share/bottlerocket/guests/inner"

  [build-dependencies]
  inner-variant = { path = "../inner-variant" }

`buildsys build-variant` validates each entry: the key must appear in
`[build-dependencies]`, the target must itself be a `build-variant`,
the value must be an absolute install path, and a variant may not
reference itself. Validated entries are threaded through a
`GUEST_IMAGES` build-arg (newline-delimited
`<guest>:<install_path>:build/images/<arch>-<guest>/<version>`) into the
`imgbuild` Dockerfile stage, where `rpm2img` (via the new
`guest-images-helper`) `cp -a`s each guest's image directory into
`${ROOT_MOUNT}<install_path>` after `rpm -iv` and before SELinux
relabel, so embedded files inherit correct labels.

Tests:
- Unit: `test_build_variant_with_guest_images`,
  `test_build_variant_without_guest_images`,
  `test_build_type_default_package_unchanged`, plus
  `validate_guest_image_entries` and `guest_image_variant_deps`
  coverage for invalid names/paths, self-reference, missing build-dep,
  transitive-only build-dep, and the happy path.
- Fixtures: `tests/projects/guest-images-kit` (host wrapper-variant
  embedding an inner-variant) and `guest-images-graph` (direct,
  transitive, and self-referential guest deps).
- Integration (`#[ignore]`, requires Docker):
  `test_twoliter_build_variant_consumes_guest_images` asserts the
  guest variant builds transitively and the host variant produces
  image artifacts.
@jmt-lab jmt-lab force-pushed the feat/images-package branch from f7cd97a to 3f8f8bf Compare July 7, 2026 22:17
Comment thread twoliter/embedded/rpm2img
Comment on lines 309 to 312
# Write the inventory.
mkdir -p "${ROOT_MOUNT}/usr/share/bottlerocket"
printf "%s\n" "${INVENTORY_DATA}" >"${ROOT_MOUNT}/usr/share/bottlerocket/application-inventory.json"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to flag this for discussion - how we might include guest OS application inventory in the host

One option is to merge the guest package inventory into the host application inventory. We can distinguish between guest OS and host OS packages clearly, such as a -guest suffix to all package names appearing in the one application-inventory that are from the guest OS. This will be necessary i.e. if names are shared between guest and host - we can't have overwriting entries.

The other option would be to provide guest inventory in the host as a completely separate file, but this wouldn't integrate out-of-the box with any tooling around inventory that expects just application-inventory.json.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Playing devil's advocate a bit: Why not just merge them into a single list and not distinguish between the two? At the end of the day if ArtifactA-1.0 is present in both the guest and the host, we will need patch that host, and all artifacts regardless of where they come from. If one of the artifacts is missed, then ArtifactA-1.0 and ArtifactA-1.1 will show up in the resulting SBOM, right?

# destructive operations. Do not add top-level side effects here.

# Suffixes produced by `compress_image` / `symlink_image` in `imghelper`. Keep
# this list in sync with the artifacts emitted by an image build.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What feedback mechanism exists to tell you when this list is out of sync? For example, warnings?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants