Skip to content

Commit 03c5c8c

Browse files
committed
tmt: Add source image archive fixtures
Tests that need the original image configuration cannot use a composefs copy-to-storage export, which regenerates it. Let plans request an OCI archive of the install image with export_image. Provide a temporary fixture through the bcvk runner and capture the image before reinstall cleanup for Packit. Expose its guest path through BOOTC_source_image_archive. Generated-by: AI Signed-off-by: Alexander Larsson <alexl@redhat.com>
1 parent 27dd410 commit 03c5c8c

2 files changed

Lines changed: 91 additions & 1 deletion

File tree

‎crates/xtask/src/tmt.rs‎

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const COMMON_INST_ARGS: &[&str] = &["--label=bootc.test=1"];
1919

2020
// Metadata field names
2121
const FIELD_TRY_BIND_STORAGE: &str = "try_bind_storage";
22+
const FIELD_EXPORT_IMAGE: &str = "export_image";
2223
const FIELD_SUMMARY: &str = "summary";
2324
const FIELD_ADJUST: &str = "adjust";
2425
const FIELD_ENABLED: &str = "enabled";
@@ -38,6 +39,7 @@ const RUST_TESTS_COMMAND: &str = "bootc-integration-tests booted";
3839
const BCVK_OPT_BIND_STORAGE_RO: &str = "--bind-storage-ro";
3940
const ENV_BOOTC_UPGRADE_IMAGE: &str = "BOOTC_upgrade_image";
4041
const ENV_BOOTC_BRIDGE_IMAGE: &str = "BOOTC_bridge_image";
42+
const ENV_BOOTC_SOURCE_IMAGE_ARCHIVE: &str = "BOOTC_source_image_archive";
4143

4244
// Distro identifiers
4345
const DISTRO_CENTOS_9: &str = "centos-9";
@@ -272,12 +274,13 @@ fn verify_ssh_connectivity(sh: &Shell, port: u16, key_path: &Utf8Path) -> Result
272274
#[derive(Debug, Default)]
273275
struct PlanMetadata {
274276
try_bind_storage: bool,
277+
export_image: bool,
275278
skip_if_composefs: bool,
276279
skip_if_ostree: bool,
277280
skip_if_uki: bool,
278281
}
279282

280-
/// Parse integration.fmf to extract extra-try_bind_storage for all plans
283+
/// Parse integration.fmf to extract harness metadata for all plans.
281284
#[context("Parsing integration.fmf")]
282285
fn parse_plan_metadata(
283286
plans_file: &Utf8Path,
@@ -305,6 +308,18 @@ fn parse_plan_metadata(
305308
continue;
306309
};
307310

311+
if let Some(export_image) = plan_data
312+
.get(serde_yaml::Value::String(format!(
313+
"extra-{FIELD_EXPORT_IMAGE}"
314+
)))
315+
.and_then(|v| v.as_bool())
316+
{
317+
plan_metadata
318+
.entry(plan_name.to_string())
319+
.or_default()
320+
.export_image = export_image;
321+
}
322+
308323
if let Some(try_bind) = plan_data.get(&serde_yaml::Value::String(format!(
309324
"extra-{}",
310325
FIELD_TRY_BIND_STORAGE
@@ -550,6 +565,34 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> {
550565
// Reset plan-specific environment variables
551566
tmt_env_vars.clear();
552567

568+
let _source_archive = if plan_metadata
569+
.iter()
570+
.find(|(key, _)| plan.ends_with(key.as_str()))
571+
.is_some_and(|(_, metadata)| metadata.export_image)
572+
{
573+
let fixture = tempfile::Builder::new()
574+
.prefix("bootc-source-")
575+
.tempdir_in(sh.current_dir().join("tmt/tests"))?;
576+
let fixture_path = Utf8Path::from_path(fixture.path())
577+
.context("Converting image fixture path to UTF-8")?;
578+
let archive = fixture_path.join("image.oci.tar");
579+
cmd!(
580+
sh,
581+
"podman save -q --format oci-archive -o {archive} {image}"
582+
)
583+
.run()
584+
.context("Exporting test source image")?;
585+
let fixture_name = fixture_path
586+
.file_name()
587+
.context("Image fixture directory name")?;
588+
tmt_env_vars.push(format!(
589+
"{ENV_BOOTC_SOURCE_IMAGE_ARCHIVE}={fixture_name}/image.oci.tar"
590+
));
591+
Some(fixture)
592+
} else {
593+
None
594+
};
595+
553596
// Get bcvk-opts based on plan metadata and distro support
554597
let plan_bcvk_opts = {
555598
let supports_bind_storage_ro = distro_supports_bind_storage_ro(&distro);
@@ -1050,6 +1093,7 @@ struct TestDef {
10501093
test_command: String,
10511094
/// Whether this test wants to try bind storage (if distro supports it)
10521095
try_bind_storage: bool,
1096+
export_image: bool,
10531097
/// Whether to skip this test for composefs backend
10541098
skip_if_composefs: bool,
10551099
/// Whether to skip this test for ostree backend
@@ -1238,6 +1282,12 @@ fn generate_integration() -> Result<(String, String)> {
12381282
.and_then(|v| v.as_bool())
12391283
.unwrap_or(false);
12401284

1285+
let export_image = metadata
1286+
.extra
1287+
.get(FIELD_EXPORT_IMAGE)
1288+
.and_then(|v| v.as_bool())
1289+
.unwrap_or(false);
1290+
12411291
let skip_if_ostree = metadata
12421292
.extra
12431293
.as_mapping()
@@ -1261,6 +1311,7 @@ fn generate_integration() -> Result<(String, String)> {
12611311
name: display_name,
12621312
test_command,
12631313
try_bind_storage,
1314+
export_image,
12641315
skip_if_composefs,
12651316
skip_if_ostree,
12661317
skip_if_uki,
@@ -1385,6 +1436,22 @@ fn generate_integration() -> Result<(String, String)> {
13851436
);
13861437
}
13871438

1439+
if test.export_image {
1440+
plan_value.insert(
1441+
serde_yaml::Value::String(format!("extra-{FIELD_EXPORT_IMAGE}")),
1442+
serde_yaml::Value::Bool(true),
1443+
);
1444+
let mut environment = serde_yaml::Mapping::new();
1445+
environment.insert(
1446+
serde_yaml::Value::String(ENV_BOOTC_SOURCE_IMAGE_ARCHIVE.to_string()),
1447+
serde_yaml::Value::String("/sysroot/bootc-source.oci.tar".to_string()),
1448+
);
1449+
plan_value.insert(
1450+
serde_yaml::Value::String("environment".to_string()),
1451+
serde_yaml::Value::Mapping(environment),
1452+
);
1453+
}
1454+
13881455
if test.skip_if_composefs {
13891456
plan_value.insert(
13901457
serde_yaml::Value::String(format!("extra-{}", FIELD_FIXME_SKIP_IF_COMPOSEFS)),
@@ -1614,4 +1681,23 @@ use anyhow::Result;
16141681

16151682
assert!(parse_tmt_metadata(content, "#").unwrap().is_none());
16161683
}
1684+
1685+
#[test]
1686+
fn test_parse_plan_image_export() -> Result<()> {
1687+
let file = tempfile::NamedTempFile::new()?;
1688+
let path = Utf8Path::from_path(file.path()).unwrap();
1689+
for (value, expected) in [("true", true), ("false", false), ("invalid", false)] {
1690+
std::fs::write(
1691+
path,
1692+
format!(
1693+
"/plan-51-switch-from-delta:\n extra-export_image: {value}\n extra-try_bind_storage: true\n"
1694+
),
1695+
)?;
1696+
let plans = parse_plan_metadata(path)?;
1697+
let plan = &plans["/plan-51-switch-from-delta"];
1698+
assert_eq!(plan.export_image, expected);
1699+
assert!(plan.try_bind_storage);
1700+
}
1701+
Ok(())
1702+
}
16171703
}

‎hack/provision-packit.sh‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ ls -al "$BOOTC_TEMPDIR"
8888
# Do not use just because it's only available on Fedora, not on CS and RHEL
8989
podman build --jobs=4 --from "$BASE" -v "$BOOTC_TEMPDIR":/bootc-test:z -t localhost/bootc -f "${BOOTC_TEMPDIR}/Containerfile.packit" "$BOOTC_TEMPDIR"
9090

91+
if [[ -n "${BOOTC_source_image_archive:-}" ]]; then
92+
podman save --format oci-archive -o "${BOOTC_source_image_archive#/sysroot}" localhost/bootc
93+
fi
94+
9195
# Keep these in sync with what's used in hack/lbi
9296
podman pull -q --retry 5 --retry-delay 5s quay.io/curl/curl:latest quay.io/curl/curl-base:latest registry.access.redhat.com/ubi9/podman:latest
9397

0 commit comments

Comments
 (0)