11//! The main entrypoint for the bootc system reinstallation CLI
22
3- use anyhow:: { Context , Result , ensure } ;
4- use bootc_utils:: CommandRunExt ;
3+ use anyhow:: { ensure , Context , Result } ;
4+ use bootc_utils:: { CommandRunExt , ResultExt } ;
55use clap:: Parser ;
66use fn_error_context:: context;
77use rustix:: process:: getuid;
@@ -10,11 +10,14 @@ use std::time::Duration;
1010mod btrfs;
1111mod config;
1212mod lvm;
13+ mod os_release;
1314mod podman;
1415mod prompt;
1516pub ( crate ) mod users;
1617
1718const ROOT_KEY_MOUNT_POINT : & str = "/bootc_authorized_ssh_keys/root" ;
19+ const ETC_OS_RELEASE : & str = "/etc/os-release" ;
20+ const USR_LIB_OS_RELEASE : & str = "/usr/lib/os-release" ;
1821
1922/// Reinstall the system using the provided bootc container.
2023///
@@ -24,17 +27,52 @@ const ROOT_KEY_MOUNT_POINT: &str = "/bootc_authorized_ssh_keys/root";
2427/// If the environment variable BOOTC_REINSTALL_CONFIG is set, it must be a YAML
2528/// file with a single member `bootc_image` that specifies the image to install.
2629/// This will take precedence over the CLI.
27- #[ derive( clap:: Parser ) ]
2830pub ( crate ) struct ReinstallOpts {
2931 /// The bootc image to install
3032 pub ( crate ) image : String ,
3133 // Note if we ever add any other options here,
34+ pub ( crate ) composefs_backend : bool ,
35+ }
36+
37+ #[ derive( clap:: Parser ) ]
38+ pub ( crate ) struct ReinstallOptsArgs {
39+ /// The bootc image to install
40+ pub ( crate ) image : Option < String > ,
41+ // Note if we ever add any other options here,
3242 #[ arg( long) ]
3343 pub ( crate ) composefs_backend : bool ,
3444}
3545
46+ impl ReinstallOptsArgs {
47+ pub ( crate ) fn build ( self ) -> Result < ReinstallOpts > {
48+ let image = if let Some ( image) = self . image {
49+ image
50+ } else {
51+ [ ETC_OS_RELEASE , USR_LIB_OS_RELEASE ]
52+ . iter ( )
53+ . find_map ( |path| {
54+ os_release:: get_bootc_image_from_file ( path)
55+ . log_err_default ( )
56+ . filter ( |s| !s. is_empty ( ) )
57+ } )
58+ . ok_or_else ( || {
59+ anyhow:: anyhow!(
60+ "No image provided. Specify an image or set BOOTC_IMAGE in os-release."
61+ )
62+ } ) ?
63+ } ;
64+
65+ Ok ( ReinstallOpts {
66+ image,
67+ composefs_backend : self . composefs_backend ,
68+ } )
69+ }
70+ }
71+
3672#[ context( "run" ) ]
3773fn run ( ) -> Result < ( ) > {
74+ let args = ReinstallOptsArgs :: parse ( ) ;
75+
3876 // We historically supported an environment variable providing a config to override the image, so
3977 // keep supporting that. I'm considering deprecating that though.
4078 let opts = if let Some ( config) = config:: ReinstallConfig :: load ( ) . context ( "loading config" ) ? {
@@ -43,8 +81,8 @@ fn run() -> Result<()> {
4381 composefs_backend : config. composefs_backend ,
4482 }
4583 } else {
46- // Otherwise an image is required.
47- ReinstallOpts :: parse ( )
84+ // Otherwise an image is specified via the CLI or fallback to the os-release
85+ args . build ( ) ?
4886 } ;
4987
5088 bootc_utils:: initialize_tracing ( ) ;
0 commit comments