@@ -22,6 +22,8 @@ const FIELD_TRY_BIND_STORAGE: &str = "try_bind_storage";
2222const FIELD_SUMMARY : & str = "summary" ;
2323const FIELD_ADJUST : & str = "adjust" ;
2424
25+ const FIELD_WORKS_FOR_COMPOSEFS : & str = "works_for_composefs" ;
26+
2527// bcvk options
2628const BCVK_OPT_BIND_STORAGE_RO : & str = "--bind-storage-ro" ;
2729const ENV_BOOTC_UPGRADE_IMAGE : & str = "BOOTC_upgrade_image" ;
@@ -247,9 +249,17 @@ fn verify_ssh_connectivity(sh: &Shell, port: u16, key_path: &Utf8Path) -> Result
247249 )
248250}
249251
252+ #[ derive( Debug ) ]
253+ struct PlanMetadata {
254+ try_bind_storage : bool ,
255+ works_for_composefs : bool ,
256+ }
257+
250258/// Parse integration.fmf to extract extra-try_bind_storage for all plans
251259#[ context( "Parsing integration.fmf" ) ]
252- fn parse_plan_metadata ( plans_file : & Utf8Path ) -> Result < std:: collections:: HashMap < String , bool > > {
260+ fn parse_plan_metadata (
261+ plans_file : & Utf8Path ,
262+ ) -> Result < std:: collections:: HashMap < String , PlanMetadata > > {
253263 let content = std:: fs:: read_to_string ( plans_file) ?;
254264 let yaml = serde_yaml:: from_str :: < serde_yaml:: Value > ( & content)
255265 . context ( "Failed to parse integration.fmf YAML" ) ?;
@@ -258,7 +268,8 @@ fn parse_plan_metadata(plans_file: &Utf8Path) -> Result<std::collections::HashMa
258268 anyhow:: bail!( "Expected YAML mapping in integration.fmf" ) ;
259269 } ;
260270
261- let mut plan_metadata = std:: collections:: HashMap :: new ( ) ;
271+ let mut plan_metadata: std:: collections:: HashMap < String , PlanMetadata > =
272+ std:: collections:: HashMap :: new ( ) ;
262273
263274 for ( key, value) in mapping {
264275 let Some ( plan_name) = key. as_str ( ) else {
@@ -271,12 +282,34 @@ fn parse_plan_metadata(plans_file: &Utf8Path) -> Result<std::collections::HashMa
271282 let Some ( plan_data) = value. as_mapping ( ) else {
272283 continue ;
273284 } ;
285+
274286 if let Some ( try_bind) = plan_data. get ( & serde_yaml:: Value :: String ( format ! (
275287 "extra-{}" ,
276288 FIELD_TRY_BIND_STORAGE
277289 ) ) ) {
278290 if let Some ( b) = try_bind. as_bool ( ) {
279- plan_metadata. insert ( plan_name. to_string ( ) , b) ;
291+ plan_metadata
292+ . entry ( plan_name. to_string ( ) )
293+ . and_modify ( |m| m. try_bind_storage = b)
294+ . or_insert ( PlanMetadata {
295+ try_bind_storage : b,
296+ works_for_composefs : false ,
297+ } ) ;
298+ }
299+ }
300+
301+ if let Some ( works_for_composefs) = plan_data. get ( & serde_yaml:: Value :: String ( format ! (
302+ "extra-{}" ,
303+ FIELD_WORKS_FOR_COMPOSEFS
304+ ) ) ) {
305+ if let Some ( b) = works_for_composefs. as_bool ( ) {
306+ plan_metadata
307+ . entry ( plan_name. to_string ( ) )
308+ . and_modify ( |m| m. works_for_composefs = b)
309+ . or_insert ( PlanMetadata {
310+ works_for_composefs : b,
311+ try_bind_storage : false ,
312+ } ) ;
280313 }
281314 }
282315 }
@@ -359,18 +392,30 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> {
359392 . filter ( |line| !line. is_empty ( ) && line. starts_with ( "/" ) )
360393 . collect ( ) ;
361394
395+ let original_plans_count = plans. len ( ) ;
396+
362397 // Filter plans based on user arguments
363398 if !filter_args. is_empty ( ) {
364- let original_count = plans. len ( ) ;
365399 plans. retain ( |plan| filter_args. iter ( ) . any ( |arg| plan. contains ( arg. as_str ( ) ) ) ) ;
366- if plans. len ( ) < original_count {
367- println ! (
368- "Filtered from {} to {} plan(s) based on arguments: {:?}" ,
369- original_count,
370- plans. len( ) ,
371- filter_args
372- ) ;
373- }
400+ }
401+
402+ if args. composefs_backend {
403+ plans. retain ( |plan| {
404+ plan_metadata
405+ . iter ( )
406+ . find ( |( key, _) | plan. ends_with ( key. as_str ( ) ) )
407+ . map ( |( _, v) | v. works_for_composefs )
408+ . unwrap_or ( false )
409+ } ) ;
410+ }
411+
412+ if plans. len ( ) < original_plans_count {
413+ println ! (
414+ "Filtered from {} to {} plan(s) based on arguments: {:?}" ,
415+ original_plans_count,
416+ plans. len( ) ,
417+ filter_args
418+ ) ;
374419 }
375420
376421 if plans. is_empty ( ) {
@@ -412,7 +457,7 @@ pub(crate) fn run_tmt(sh: &Shell, args: &RunTmtArgs) -> Result<()> {
412457 let try_bind_storage = plan_metadata
413458 . iter ( )
414459 . find ( |( key, _) | plan. ends_with ( key. as_str ( ) ) )
415- . map ( |( _, & v) | v)
460+ . map ( |( _, v) | v. try_bind_storage )
416461 . unwrap_or ( false ) ;
417462
418463 let mut opts = Vec :: new ( ) ;
@@ -863,6 +908,8 @@ struct TestDef {
863908 test_command : String ,
864909 /// Whether this test wants to try bind storage (if distro supports it)
865910 try_bind_storage : bool ,
911+ /// Whether this test will work for composefs backend
912+ works_for_composefs : bool ,
866913 /// TMT fmf attributes to pass through (summary, duration, adjust, etc.)
867914 tmt : serde_yaml:: Value ,
868915}
@@ -953,11 +1000,23 @@ pub(crate) fn update_integration() -> Result<()> {
9531000 . and_then ( |v| v. as_bool ( ) )
9541001 . unwrap_or ( false ) ;
9551002
1003+ let works_for_composefs = metadata
1004+ . extra
1005+ . as_mapping ( )
1006+ . and_then ( |m| {
1007+ m. get ( & serde_yaml:: Value :: String (
1008+ FIELD_WORKS_FOR_COMPOSEFS . to_string ( ) ,
1009+ ) )
1010+ } )
1011+ . and_then ( |v| v. as_bool ( ) )
1012+ . unwrap_or ( false ) ;
1013+
9561014 tests. push ( TestDef {
9571015 number : metadata. number ,
9581016 name : display_name,
9591017 test_command,
9601018 try_bind_storage,
1019+ works_for_composefs,
9611020 tmt : metadata. tmt ,
9621021 } ) ;
9631022 }
@@ -1076,6 +1135,13 @@ pub(crate) fn update_integration() -> Result<()> {
10761135 ) ;
10771136 }
10781137
1138+ if test. works_for_composefs {
1139+ plan_value. insert (
1140+ serde_yaml:: Value :: String ( format ! ( "extra-{}" , FIELD_WORKS_FOR_COMPOSEFS ) ) ,
1141+ serde_yaml:: Value :: Bool ( true ) ,
1142+ ) ;
1143+ }
1144+
10791145 plans_mapping. insert (
10801146 serde_yaml:: Value :: String ( plan_key) ,
10811147 serde_yaml:: Value :: Mapping ( plan_value) ,
0 commit comments