@@ -345,6 +345,12 @@ pub(crate) struct InstallConfigOpts {
345345 #[ clap( long) ]
346346 pub ( crate ) karg : Option < Vec < CmdlineOwned > > ,
347347
348+ /// Remove a kernel argument. This option can be provided multiple times.
349+ ///
350+ /// Example: --karg-delete=nosmt --karg=console=ttyS0,115200n8
351+ #[ clap( long) ]
352+ pub ( crate ) karg_delete : Option < Vec < String > > ,
353+
348354 /// The path to an `authorized_keys` that will be injected into the `root` account.
349355 ///
350356 /// The implementation of this uses systemd `tmpfiles.d`, writing to a file named
@@ -1124,13 +1130,18 @@ async fn install_container(
11241130
11251131 // Keep this in sync with install/completion.rs for the Anaconda fixups
11261132 let install_config_kargs = state. install_config . as_ref ( ) . and_then ( |c| c. kargs . as_ref ( ) ) ;
1133+ let install_config_karg_deletes = state
1134+ . install_config
1135+ . as_ref ( )
1136+ . and_then ( |c| c. karg_deletes . as_ref ( ) ) ;
11271137
11281138 // Final kargs, in order:
11291139 // - root filesystem kargs
11301140 // - install config kargs
11311141 // - kargs.d from container image
11321142 // - args specified on the CLI
11331143 let mut kargs = Cmdline :: new ( ) ;
1144+ let mut karg_deletes = Vec :: < & str > :: new ( ) ;
11341145
11351146 kargs. extend ( & root_setup. kargs ) ;
11361147
@@ -1142,6 +1153,19 @@ async fn install_container(
11421153
11431154 kargs. extend ( & kargsd) ;
11441155
1156+ // delete kargs before processing cli kargs, so cli kargs can override all other configs
1157+ if let Some ( install_config_karg_deletes) = install_config_karg_deletes {
1158+ for karg_delete in install_config_karg_deletes {
1159+ karg_deletes. push ( karg_delete) ;
1160+ }
1161+ }
1162+ if let Some ( deletes) = state. config_opts . karg_delete . as_ref ( ) {
1163+ for karg_delete in deletes {
1164+ karg_deletes. push ( karg_delete) ;
1165+ }
1166+ }
1167+ delete_kargs ( & mut kargs, & karg_deletes) ;
1168+
11451169 if let Some ( cli_kargs) = state. config_opts . karg . as_ref ( ) {
11461170 for karg in cli_kargs {
11471171 kargs. extend ( karg) ;
@@ -1224,6 +1248,18 @@ async fn install_container(
12241248 Ok ( ( deployment, aleph) )
12251249}
12261250
1251+ pub ( crate ) fn delete_kargs ( existing : & mut Cmdline , deletes : & Vec < & str > ) {
1252+ for delete in deletes {
1253+ if let Some ( param) = utf8:: Parameter :: parse ( & delete) {
1254+ if param. value ( ) . is_some ( ) {
1255+ existing. remove_exact ( & param) ;
1256+ } else {
1257+ existing. remove ( & param. key ( ) ) ;
1258+ }
1259+ }
1260+ }
1261+ }
1262+
12271263/// Run a command in the host mount namespace
12281264pub ( crate ) fn run_in_host_mountns ( cmd : & str ) -> Result < Command > {
12291265 let mut c = Command :: new ( bootc_utils:: reexec:: executable_path ( ) ?) ;
@@ -3085,4 +3121,21 @@ UUID=boot-uuid /boot ext4 defaults 0 0
30853121
30863122 Ok ( ( ) )
30873123 }
3124+
3125+ #[ test]
3126+ fn test_delete_kargs ( ) -> Result < ( ) > {
3127+ let mut cmdline = Cmdline :: from ( "console=tty0 quiet debug nosmt foo=bar foo=baz bar=baz" ) ;
3128+
3129+ let deletions = vec ! [ "foo=bar" , "bar" , "debug" ] ;
3130+
3131+ delete_kargs ( & mut cmdline, & deletions) ;
3132+
3133+ let result = cmdline. to_string ( ) ;
3134+ assert ! ( !result. contains( "foo=bar" ) ) ;
3135+ assert ! ( !result. contains( "bar" ) ) ;
3136+ assert ! ( !result. contains( "debug" ) ) ;
3137+ assert ! ( result. contains( "foo=baz" ) ) ;
3138+
3139+ Ok ( ( ) )
3140+ }
30883141}
0 commit comments