kata-deploy: Fix noisy caused by unformatted code

When do cargo fmt --all, some files changes as unformatted with
`cargo fmt`. This commit is just to address it.

Just use this as an example:
```
         // Generate the common drop-in files (shared with standard
         // runtimes)
-        write_common_drop_ins(config, &runtime.base_config,
         &config_d_dir, container_runtime)?;
+        write_common_drop_ins(
+            config,
+            &runtime.base_config,
+            &config_d_dir,
+            container_runtime,
+        )?;
```

Signed-off-by: Alex Lyn <alex.lyn@antgroup.com>
This commit is contained in:
Alex Lyn
2026-04-08 09:14:38 +08:00
committed by Zvonko Kaiser
parent 6269b3ecde
commit c00f895338
7 changed files with 236 additions and 131 deletions

View File

@@ -76,8 +76,12 @@ pub async fn install_artifacts(config: &Config, container_runtime: &str) -> Resu
// Create the installation directory if it doesn't exist
// fs::create_dir_all handles existing directories gracefully (returns Ok if already exists)
fs::create_dir_all(&config.host_install_dir)
.with_context(|| format!("Failed to create installation directory: {}", config.host_install_dir))?;
fs::create_dir_all(&config.host_install_dir).with_context(|| {
format!(
"Failed to create installation directory: {}",
config.host_install_dir
)
})?;
// Verify the path exists and is a directory (not a file)
let install_path = Path::new(&config.host_install_dir);
@@ -182,7 +186,11 @@ fn write_common_drop_ins(
let kernel_params_content = generate_kernel_params_drop_in(config, shim)?;
if !kernel_params_content.is_empty() {
info!(" - Kernel parameters: configured");
write_drop_in_file(config_d_dir, "30-kernel-params.toml", &kernel_params_content)?;
write_drop_in_file(
config_d_dir,
"30-kernel-params.toml",
&kernel_params_content,
)?;
}
Ok(())
@@ -239,7 +247,12 @@ fn install_custom_runtime_configs(config: &Config, container_runtime: &str) -> R
}
// Generate the common drop-in files (shared with standard runtimes)
write_common_drop_ins(config, &runtime.base_config, &config_d_dir, container_runtime)?;
write_common_drop_ins(
config,
&runtime.base_config,
&config_d_dir,
container_runtime,
)?;
// Copy user-provided drop-in file if provided (at 50-overrides.toml)
if let Some(ref drop_in_src) = runtime.drop_in_file {
@@ -342,8 +355,12 @@ fn copy_artifacts(src: &str, dst: &str) -> Result<()> {
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {}
Err(e) => return Err(e.into()),
}
std::os::unix::fs::symlink(&new_target, &dst_path)
.with_context(|| format!("Failed to create symlink {:?} -> {:?}", dst_path, new_target))?;
std::os::unix::fs::symlink(&new_target, &dst_path).with_context(|| {
format!(
"Failed to create symlink {:?} -> {:?}",
dst_path, new_target
)
})?;
} else {
if let Some(parent) = dst_path.parent() {
fs::create_dir_all(parent)?;
@@ -459,13 +476,18 @@ fn setup_runtime_directory(config: &Config, shim: &str) -> Result<()> {
// fs::copy follows symlinks and would write to the wrong location
let dest_path = Path::new(&dest_config_file);
if dest_path.exists() || dest_path.is_symlink() {
fs::remove_file(&dest_config_file)
.with_context(|| format!("Failed to remove existing config: {}", dest_config_file))?;
fs::remove_file(&dest_config_file).with_context(|| {
format!("Failed to remove existing config: {}", dest_config_file)
})?;
}
// Copy the base config file
fs::copy(&original_config_file, &dest_config_file)
.with_context(|| format!("Failed to copy config: {} -> {}", original_config_file, dest_config_file))?;
fs::copy(&original_config_file, &dest_config_file).with_context(|| {
format!(
"Failed to copy config: {} -> {}",
original_config_file, dest_config_file
)
})?;
// Add warning comment to inform users about drop-in files
add_kata_deploy_warning(Path::new(&dest_config_file))?;
@@ -484,8 +506,9 @@ fn remove_runtime_directory(config: &Config, shim: &str) -> Result<()> {
);
if Path::new(&runtime_config_dir).exists() {
fs::remove_dir_all(&runtime_config_dir)
.with_context(|| format!("Failed to remove runtime directory: {}", runtime_config_dir))?;
fs::remove_dir_all(&runtime_config_dir).with_context(|| {
format!("Failed to remove runtime directory: {}", runtime_config_dir)
})?;
log::debug!("Removed runtime directory: {}", runtime_config_dir);
}
@@ -514,7 +537,8 @@ async fn configure_shim_config(config: &Config, shim: &str, container_runtime: &
);
let config_d_dir = format!("{}/config.d", runtime_config_dir);
let kata_config_file = Path::new(&runtime_config_dir).join(format!("configuration-{shim}.toml"));
let kata_config_file =
Path::new(&runtime_config_dir).join(format!("configuration-{shim}.toml"));
// The configuration file (symlink) should exist after setup_runtime_directory()
if !kata_config_file.exists() {
@@ -545,8 +569,8 @@ async fn configure_shim_config(config: &Config, shim: &str, container_runtime: &
/// Reads the current value (defaulting to "false" if not found), and if it's not "true",
/// logs the update and sets it to "true".
fn set_toml_bool_to_true(config_file: &Path, path: &str) -> Result<()> {
let current_value = toml_utils::get_toml_value(config_file, path)
.unwrap_or_else(|_| "false".to_string());
let current_value =
toml_utils::get_toml_value(config_file, path).unwrap_or_else(|_| "false".to_string());
if current_value != "true" {
log::debug!(
"Updating {} in {}: old=\"{}\" new=\"true\"",
@@ -636,8 +660,9 @@ fn get_hypervisor_path(config: &Config, shim: &str) -> Result<String> {
if is_qemu_shim(shim) {
// For QEMU shims, use the wrapper script that adds firmware paths
// create_qemu_wrapper_script always returns Some for QEMU shims
create_qemu_wrapper_script(config, shim)?
.ok_or_else(|| anyhow::anyhow!("QEMU wrapper script should always be created for QEMU shims"))
create_qemu_wrapper_script(config, shim)?.ok_or_else(|| {
anyhow::anyhow!("QEMU wrapper script should always be created for QEMU shims")
})
} else {
// For non-QEMU shims, use the appropriate hypervisor binary
let binary = match shim {
@@ -673,20 +698,41 @@ fn generate_installation_prefix_drop_in(config: &Config, shim: &str) -> Result<S
}
// Common paths for all hypervisors
content.push_str(&format!("kernel = \"{}/share/kata-containers/vmlinux.container\"\n", config.dest_dir));
content.push_str(&format!("image = \"{}/share/kata-containers/kata-containers.img\"\n", config.dest_dir));
content.push_str(&format!("initrd = \"{}/share/kata-containers/kata-containers-initrd.img\"\n", config.dest_dir));
content.push_str(&format!(
"kernel = \"{}/share/kata-containers/vmlinux.container\"\n",
config.dest_dir
));
content.push_str(&format!(
"image = \"{}/share/kata-containers/kata-containers.img\"\n",
config.dest_dir
));
content.push_str(&format!(
"initrd = \"{}/share/kata-containers/kata-containers-initrd.img\"\n",
config.dest_dir
));
// QEMU-specific paths (firmware is only relevant for QEMU)
if is_qemu_shim(shim) {
content.push_str(&format!("firmware = \"{}/share/kata-containers/firmware/\"\n", config.dest_dir));
content.push_str(&format!("firmware_volume = \"{}/share/kata-containers/firmware/\"\n", config.dest_dir));
content.push_str(&format!(
"firmware = \"{}/share/kata-containers/firmware/\"\n",
config.dest_dir
));
content.push_str(&format!(
"firmware_volume = \"{}/share/kata-containers/firmware/\"\n",
config.dest_dir
));
}
// Firecracker-specific paths (jailer is only for Firecracker)
if shim == "fc" || shim == "firecracker" {
content.push_str(&format!("jailer_path = \"{}/bin/jailer\"\n", config.dest_dir));
content.push_str(&format!("valid_jailer_paths = [\"{}/bin/jailer\"]\n", config.dest_dir));
content.push_str(&format!(
"jailer_path = \"{}/bin/jailer\"\n",
config.dest_dir
));
content.push_str(&format!(
"valid_jailer_paths = [\"{}/bin/jailer\"]\n",
config.dest_dir
));
}
Ok(content)
@@ -738,16 +784,14 @@ fn get_proxy_value_for_shim(proxy_var: &Option<String>, shim: &str) -> Option<St
match proxy_var {
Some(proxy) if !proxy.is_empty() && proxy.contains('=') => {
// Per-shim format: "qemu-tdx=http://proxy:8080;qemu-snp=http://proxy2:8080"
proxy
.split(';')
.find_map(|m| {
let parts: Vec<&str> = m.splitn(2, '=').collect();
if parts.len() == 2 && parts[0] == shim {
Some(parts[1].to_string())
} else {
None
}
})
proxy.split(';').find_map(|m| {
let parts: Vec<&str> = m.splitn(2, '=').collect();
if parts.len() == 2 && parts[0] == shim {
Some(parts[1].to_string())
} else {
None
}
})
}
Some(proxy) if !proxy.is_empty() => Some(proxy.clone()),
_ => None,
@@ -770,8 +814,8 @@ fn read_base_kernel_params(config: &Config, shim: &str) -> Result<String> {
}
let kernel_params_path = format!("hypervisor.{}.kernel_params", hypervisor_name);
let base_params = toml_utils::get_toml_value(config_path, &kernel_params_path)
.unwrap_or_default();
let base_params =
toml_utils::get_toml_value(config_path, &kernel_params_path).unwrap_or_default();
// Remove surrounding quotes if present
Ok(base_params.trim_matches('"').to_string())
@@ -1100,5 +1144,4 @@ mod tests {
"following the symlink should yield the real content"
);
}
}

View File

@@ -91,7 +91,8 @@ pub async fn configure_snapshotter(
Some(id) => id.as_str(),
None => containerd::get_containerd_pluginid(&paths.config_file)?,
};
let pluginid = containerd::pluginid_for_snapshotter_annotations(runtime_plugin_id, &paths.config_file)?;
let pluginid =
containerd::pluginid_for_snapshotter_annotations(runtime_plugin_id, &paths.config_file)?;
let configuration_file: std::path::PathBuf = if paths.use_drop_in {
// Only add /host prefix if path is not in /etc/containerd (which is mounted from host)

View File

@@ -189,14 +189,11 @@ impl Config {
let default_shim_for_arch = get_arch_var("DEFAULT_SHIM", "qemu", &arch);
// Only use arch-specific variable for allowed hypervisor annotations
let allowed_hypervisor_annotations_for_arch = get_arch_var(
"ALLOWED_HYPERVISOR_ANNOTATIONS",
"",
&arch,
)
.split_whitespace()
.map(|s| s.to_string())
.collect();
let allowed_hypervisor_annotations_for_arch =
get_arch_var("ALLOWED_HYPERVISOR_ANNOTATIONS", "", &arch)
.split_whitespace()
.map(|s| s.to_string())
.collect();
// Only use arch-specific variable for snapshotter handler mapping
let snapshotter_handler_mapping_for_arch =
@@ -208,7 +205,9 @@ impl Config {
let pull_type_mapping_for_arch = get_arch_var_or_base("PULL_TYPE_MAPPING", &arch);
let installation_prefix = env::var("INSTALLATION_PREFIX").ok().filter(|s| !s.is_empty());
let installation_prefix = env::var("INSTALLATION_PREFIX")
.ok()
.filter(|s| !s.is_empty());
let dest_dir = match installation_prefix {
Some(ref prefix) => {
if !prefix.starts_with('/') {
@@ -258,15 +257,12 @@ impl Config {
.map(|s| s.split(',').map(|s| s.trim().to_string()).collect());
// Only use arch-specific variable for experimental force guest pull
let experimental_force_guest_pull_for_arch = get_arch_var(
"EXPERIMENTAL_FORCE_GUEST_PULL",
"",
&arch,
)
.split(',')
.filter(|s| !s.is_empty())
.map(|s| s.trim().to_string())
.collect();
let experimental_force_guest_pull_for_arch =
get_arch_var("EXPERIMENTAL_FORCE_GUEST_PULL", "", &arch)
.split(',')
.filter(|s| !s.is_empty())
.map(|s| s.trim().to_string())
.collect();
// Parse custom runtimes from ConfigMap
let custom_runtimes_enabled =
@@ -531,7 +527,8 @@ impl Config {
use crate::runtime::manager;
// Check if drop-in files can be used based on containerd version
let use_drop_in = manager::is_containerd_capable_of_using_drop_in_files(self, runtime).await?;
let use_drop_in =
manager::is_containerd_capable_of_using_drop_in_files(self, runtime).await?;
let paths = match runtime {
"k0s-worker" | "k0s-controller" => ContainerdPaths {
@@ -556,12 +553,10 @@ impl Config {
// versioned drop-in dir (config.toml.d or config-v3.toml.d). If the import is
// missing we bail; the cluster must configure the template with the import
// (e.g. in tests or via a custom k3s/RKE2 setup). Refs: docs.k3s.io/advanced#configuring-containerd
let container_runtime_version = k8s::get_node_field(
self,
".status.nodeInfo.containerRuntimeVersion",
)
.await
.ok();
let container_runtime_version =
k8s::get_node_field(self, ".status.nodeInfo.containerRuntimeVersion")
.await
.ok();
let use_v3 = k3s_rke2_resolve_use_v3(
&self.containerd_conf_file,
container_runtime_version.as_deref(),
@@ -894,14 +889,17 @@ mod tests {
#[serial]
#[test]
fn test_k3s_rke2_rendered_config_path() {
assert_eq!(k3s_rke2_rendered_config_path(), "/etc/containerd/config.toml");
assert_eq!(
k3s_rke2_rendered_config_path(),
"/etc/containerd/config.toml"
);
}
#[rstest]
#[case(
"imports = [\"/var/lib/rancher/k3s/agent/etc/containerd/config.toml.d/*.toml\"]\n",
false,
true,
true
)]
#[case("version = 2\n", false, false)]
#[case("imports = [\"/path/config-v3.toml.d/*.toml\"]", true, true)]

View File

@@ -69,7 +69,10 @@ async fn main() -> Result<()> {
let mut sigterm = match signal(SignalKind::terminate()) {
Ok(s) => s,
Err(e) => {
log::warn!("Failed to register SIGTERM handler: {}, sleeping forever", e);
log::warn!(
"Failed to register SIGTERM handler: {}, sleeping forever",
e
);
std::future::pending::<()>().await;
return Ok(());
}

View File

@@ -144,8 +144,7 @@ fn write_containerd_runtime_config(
config_file,
&format!(
".plugins.{}.runtime_platforms.\"{}\".snapshotter",
CONTAINERD_CRI_IMAGES_PLUGIN_ID,
params.runtime_name
CONTAINERD_CRI_IMAGES_PLUGIN_ID, params.runtime_name
),
snapshotter,
)?;
@@ -280,9 +279,7 @@ pub async fn configure_custom_containerd_runtime(
),
config_path: format!(
"\"{}/share/defaults/kata-containers/custom-runtimes/{}/configuration-{}.toml\"",
config.dest_dir,
custom_runtime.handler,
custom_runtime.base_config
config.dest_dir, custom_runtime.handler, custom_runtime.base_config
),
pod_annotations,
snapshotter,
@@ -339,11 +336,7 @@ pub async fn configure_containerd(config: &Config, runtime: &str) -> Result<()>
let imports_path = ".imports";
let drop_in_path = format!("\"{}\"", paths.drop_in_file);
toml_utils::append_to_toml_array(
Path::new(imports_file),
imports_path,
&drop_in_path,
)?;
toml_utils::append_to_toml_array(Path::new(imports_file), imports_path, &drop_in_path)?;
log::info!("Successfully added drop-in to imports array");
} else {
log::info!("Runtime auto-loads drop-in files, skipping imports");
@@ -369,10 +362,7 @@ pub async fn configure_containerd(config: &Config, runtime: &str) -> Result<()>
config.custom_runtimes.len()
);
for custom_runtime in &config.custom_runtimes {
log::info!(
"Configuring custom runtime: {}",
custom_runtime.handler
);
log::info!("Configuring custom runtime: {}", custom_runtime.handler);
configure_custom_containerd_runtime(config, runtime, custom_runtime).await?;
log::info!(
"Successfully configured custom runtime: {}",
@@ -436,12 +426,14 @@ pub async fn setup_containerd_config_files(runtime: &str, config: &Config) -> Re
Path::new("/host").join(paths.drop_in_file.trim_start_matches('/'))
};
if let Some(parent) = drop_in_path.parent() {
fs::create_dir_all(parent)
.with_context(|| format!("Failed to create K3s/RKE2 drop-in dir: {parent:?}"))?;
fs::create_dir_all(parent).with_context(|| {
format!("Failed to create K3s/RKE2 drop-in dir: {parent:?}")
})?;
}
if !drop_in_path.exists() {
fs::write(&drop_in_path, "")
.with_context(|| format!("Failed to create K3s/RKE2 drop-in file: {drop_in_path:?}"))?;
fs::write(&drop_in_path, "").with_context(|| {
format!("Failed to create K3s/RKE2 drop-in file: {drop_in_path:?}")
})?;
}
}
"k0s-worker" | "k0s-controller" => {
@@ -501,7 +493,10 @@ pub async fn containerd_snapshotter_version_check(config: &Config) -> Result<()>
.map(|s| !s.is_empty())
.unwrap_or(false);
check_containerd_snapshotter_version_support(&container_runtime_version, has_snapshotter_mapping)
check_containerd_snapshotter_version_support(
&container_runtime_version,
has_snapshotter_mapping,
)
}
fn check_containerd_erofs_version_support(container_runtime_version: &str) -> Result<()> {
@@ -609,10 +604,7 @@ mod tests {
use std::path::Path;
use tempfile::NamedTempFile;
fn make_params(
runtime_name: &str,
snapshotter: Option<&str>,
) -> ContainerdRuntimeParams {
fn make_params(runtime_name: &str, snapshotter: Option<&str>) -> ContainerdRuntimeParams {
ContainerdRuntimeParams {
runtime_name: runtime_name.to_string(),
runtime_path: "\"/opt/kata/bin/kata-runtime\"".to_string(),
@@ -673,7 +665,11 @@ mod tests {
/// pluginid_for_snapshotter_annotations maps runtime plugin id to the table where disable_snapshot_annotations lives.
#[rstest]
#[case(CONTAINERD_V3_RUNTIME_PLUGIN_ID, CONTAINERD_CRI_IMAGES_PLUGIN_ID, false)]
#[case(
CONTAINERD_V3_RUNTIME_PLUGIN_ID,
CONTAINERD_CRI_IMAGES_PLUGIN_ID,
false
)]
#[case(CONTAINERD_V2_CRI_PLUGIN_ID, CONTAINERD_CRI_CONTAINERD_TABLE_V2, false)]
#[case(CONTAINERD_LEGACY_CRI_PLUGIN_ID, "", true)]
fn test_pluginid_for_snapshotter_annotations(
@@ -709,9 +705,7 @@ mod tests {
#[rstest]
#[case(CONTAINERD_V3_RUNTIME_PLUGIN_ID)]
#[case(CONTAINERD_V2_CRI_PLUGIN_ID)]
fn test_write_containerd_runtime_config_empty_file_no_leading_newlines(
#[case] pluginid: &str,
) {
fn test_write_containerd_runtime_config_empty_file_no_leading_newlines(#[case] pluginid: &str) {
let file = NamedTempFile::new().unwrap();
let path = file.path();
std::fs::write(path, "").unwrap();
@@ -733,7 +727,12 @@ mod tests {
}
#[rstest]
#[case("containerd://1.6.28", true, false, Some("kata-deploy only supports snapshotter configuration with containerd 1.7 or newer"))]
#[case(
"containerd://1.6.28",
true,
false,
Some("kata-deploy only supports snapshotter configuration with containerd 1.7 or newer")
)]
#[case("containerd://1.6.28", false, true, None)]
#[case("containerd://1.6.0", true, false, None)]
#[case("containerd://1.6.999", true, false, None)]
@@ -750,9 +749,19 @@ mod tests {
) {
let result = check_containerd_snapshotter_version_support(version, has_mapping);
if expect_ok {
assert!(result.is_ok(), "expected ok for version={} has_mapping={}", version, has_mapping);
assert!(
result.is_ok(),
"expected ok for version={} has_mapping={}",
version,
has_mapping
);
} else {
assert!(result.is_err(), "expected err for version={} has_mapping={}", version, has_mapping);
assert!(
result.is_err(),
"expected err for version={} has_mapping={}",
version,
has_mapping
);
if let Some(sub) = expected_error_substring {
assert!(
result.unwrap_err().to_string().contains(sub),

View File

@@ -101,26 +101,65 @@ mod tests {
#[case("qemu-tdx", "/opt/kata", "/opt/kata/share/defaults/kata-containers")]
#[case("fc", "/opt/kata", "/opt/kata/share/defaults/kata-containers")]
#[case("clh", "/opt/kata", "/opt/kata/share/defaults/kata-containers")]
#[case("cloud-hypervisor", "/opt/kata", "/opt/kata/share/defaults/kata-containers/runtime-rs")]
#[case("qemu-runtime-rs", "/opt/kata", "/opt/kata/share/defaults/kata-containers/runtime-rs")]
#[case(
"cloud-hypervisor",
"/opt/kata",
"/opt/kata/share/defaults/kata-containers/runtime-rs"
)]
#[case(
"qemu-runtime-rs",
"/opt/kata",
"/opt/kata/share/defaults/kata-containers/runtime-rs"
)]
#[case("qemu", "/custom/path", "/custom/path/share/defaults/kata-containers")]
#[case("cloud-hypervisor", "/custom/path", "/custom/path/share/defaults/kata-containers/runtime-rs")]
#[case(
"cloud-hypervisor",
"/custom/path",
"/custom/path/share/defaults/kata-containers/runtime-rs"
)]
fn test_get_kata_containers_original_config_path(
#[case] shim: &str,
#[case] base_dir: &str,
#[case] expected: &str,
) {
assert_eq!(get_kata_containers_original_config_path(shim, base_dir), expected);
assert_eq!(
get_kata_containers_original_config_path(shim, base_dir),
expected
);
}
// Tests for get_kata_containers_config_path (per-shim runtime directories)
#[rstest]
#[case("qemu", "/opt/kata", "/opt/kata/share/defaults/kata-containers/runtimes/qemu")]
#[case("qemu-tdx", "/opt/kata", "/opt/kata/share/defaults/kata-containers/runtimes/qemu-tdx")]
#[case("fc", "/opt/kata", "/opt/kata/share/defaults/kata-containers/runtimes/fc")]
#[case("cloud-hypervisor", "/opt/kata", "/opt/kata/share/defaults/kata-containers/runtime-rs/runtimes/cloud-hypervisor")]
#[case("qemu-runtime-rs", "/opt/kata", "/opt/kata/share/defaults/kata-containers/runtime-rs/runtimes/qemu-runtime-rs")]
#[case("qemu", "/custom/path", "/custom/path/share/defaults/kata-containers/runtimes/qemu")]
#[case(
"qemu",
"/opt/kata",
"/opt/kata/share/defaults/kata-containers/runtimes/qemu"
)]
#[case(
"qemu-tdx",
"/opt/kata",
"/opt/kata/share/defaults/kata-containers/runtimes/qemu-tdx"
)]
#[case(
"fc",
"/opt/kata",
"/opt/kata/share/defaults/kata-containers/runtimes/fc"
)]
#[case(
"cloud-hypervisor",
"/opt/kata",
"/opt/kata/share/defaults/kata-containers/runtime-rs/runtimes/cloud-hypervisor"
)]
#[case(
"qemu-runtime-rs",
"/opt/kata",
"/opt/kata/share/defaults/kata-containers/runtime-rs/runtimes/qemu-runtime-rs"
)]
#[case(
"qemu",
"/custom/path",
"/custom/path/share/defaults/kata-containers/runtimes/qemu"
)]
fn test_get_kata_containers_config_path(
#[case] shim: &str,
#[case] base_dir: &str,
@@ -207,7 +246,10 @@ mod tests {
let runtime_path = get_kata_containers_runtime_path(shim, dest_dir);
// Expected paths for Go runtime with per-shim directory
assert_eq!(config_path, "/opt/kata/share/defaults/kata-containers/runtimes/qemu-tdx");
assert_eq!(
config_path,
"/opt/kata/share/defaults/kata-containers/runtimes/qemu-tdx"
);
assert_eq!(original_path, "/opt/kata/share/defaults/kata-containers");
assert_eq!(runtime_path, "/opt/kata/bin/containerd-shim-kata-v2");

View File

@@ -67,11 +67,7 @@ fn split_non_toml_header(content: &str) -> (&str, &str) {
/// Ensures the header ends with a newline before the TOML body.
/// Trims leading newlines from the serialized document to avoid many blank lines
/// when the file was initially empty (e.g. containerd drop-in).
fn write_toml_with_header(
file_path: &Path,
header: &str,
doc: &DocumentMut,
) -> Result<()> {
fn write_toml_with_header(file_path: &Path, header: &str, doc: &DocumentMut) -> Result<()> {
let normalized_header = if header.is_empty() {
String::new()
} else if header.ends_with('\n') {
@@ -214,7 +210,10 @@ pub fn append_to_toml_array(file_path: &Path, path: &str, value: &str) -> Result
// This is the array itself - use .get() to avoid panic on missing key
let key_exists = current.get(part.as_str()).is_some();
if !key_exists {
current.insert(part.as_str(), Item::Value(Value::Array(toml_edit::Array::new())));
current.insert(
part.as_str(),
Item::Value(Value::Array(toml_edit::Array::new())),
);
}
if let Some(Item::Value(Value::Array(arr))) = current.get_mut(part.as_str()) {
let value_item = parse_toml_value(value);
@@ -441,11 +440,7 @@ mod tests {
#[case("", "", "")]
#[case("key = \"value\"\n", "", "key = \"value\"\n")]
#[case("[plugins]\nfoo = 1\n", "", "[plugins]\nfoo = 1\n")]
#[case(
"{{ template \"base\" . }}\n",
"{{ template \"base\" . }}\n",
""
)]
#[case("{{ template \"base\" . }}\n", "{{ template \"base\" . }}\n", "")]
#[case(
"{{ template \"base\" . }}\n[plugins]\nfoo = 1\n",
"{{ template \"base\" . }}\n",
@@ -464,7 +459,11 @@ mod tests {
#[case] expected_toml: &str,
) {
let (header, toml) = split_non_toml_header(input);
assert_eq!(header, expected_header, "header mismatch for input: {:?}", input);
assert_eq!(
header, expected_header,
"header mismatch for input: {:?}",
input
);
assert_eq!(toml, expected_toml, "toml mismatch for input: {:?}", input);
}
@@ -484,7 +483,10 @@ mod tests {
.unwrap();
let content = std::fs::read_to_string(path).unwrap();
assert!(content.starts_with("{{ template \"base\" . }}\n"), "header must be preserved");
assert!(
content.starts_with("{{ template \"base\" . }}\n"),
"header must be preserved"
);
assert!(content.contains("runtime_type"), "value must be written");
let value = get_toml_value(
@@ -580,8 +582,12 @@ mod tests {
&format!("\"io.containerd.{shim}.v2\""),
)
.unwrap();
set_toml_value(path, &format!("{table}.privileged_without_host_devices"), "true")
.unwrap();
set_toml_value(
path,
&format!("{table}.privileged_without_host_devices"),
"true",
)
.unwrap();
}
let content = std::fs::read_to_string(path).unwrap();
@@ -633,7 +639,10 @@ mod tests {
)
.unwrap();
let content = std::fs::read_to_string(path).unwrap();
assert!(content.starts_with(expected_prefix), "header/prefix must be preserved");
assert!(
content.starts_with(expected_prefix),
"header/prefix must be preserved"
);
let body_start = content.strip_prefix(expected_prefix).unwrap();
assert!(
!body_start.starts_with('\n'),
@@ -782,11 +791,7 @@ mod tests {
#[case("test.string_value", "test_string", "test_string")]
#[case("test.bool_value", "true", "true")]
#[case("test.int_value", "42", "42")]
fn test_toml_value_types(
#[case] path: &str,
#[case] value: &str,
#[case] expected: &str,
) {
fn test_toml_value_types(#[case] path: &str, #[case] value: &str, #[case] expected: &str) {
let file = NamedTempFile::new().unwrap();
let file_path = file.path();
std::fs::write(file_path, "").unwrap();
@@ -827,8 +832,8 @@ mod tests {
);
// Test modifying kernel_params on real config
let current = get_toml_value(temp_path, "hypervisor.qemu.kernel_params")
.unwrap_or_default();
let current =
get_toml_value(temp_path, "hypervisor.qemu.kernel_params").unwrap_or_default();
let new_value = format!("{} agent.log=debug", current.trim_matches('"'));
let result = set_toml_value(
temp_path,
@@ -1318,7 +1323,11 @@ kernel_params = "console=hvc0"
"set" => set_toml_value(temp_path, "some.path", "\"value\""),
_ => panic!("unknown op"),
};
assert!(result.is_err(), "Should fail parsing invalid TOML (op={})", op);
assert!(
result.is_err(),
"Should fail parsing invalid TOML (op={})",
op
);
}
#[test]