fix: fmt
This commit is contained in:
+18
-6
@@ -137,7 +137,11 @@ fn extract_oci_layer(layer_path: &Path, dest: &Path) -> Result<()> {
|
||||
"Extracting OCI layer",
|
||||
)
|
||||
} else if layer_name.ends_with(".tar.xz") || layer_name.ends_with(".txz") {
|
||||
extract_with_progress(tar::Archive::new(xz2::read::XzDecoder::new(reader)), dest, "Extracting OCI layer")
|
||||
extract_with_progress(
|
||||
tar::Archive::new(xz2::read::XzDecoder::new(reader)),
|
||||
dest,
|
||||
"Extracting OCI layer",
|
||||
)
|
||||
} else if layer_name.ends_with(".tar.zst") || layer_name.ends_with(".tar.zstd") {
|
||||
extract_with_progress(
|
||||
tar::Archive::new(zstd::stream::read::Decoder::new(reader)?),
|
||||
@@ -217,18 +221,25 @@ fn extract_tar<R: std::io::Read>(reader: R, dest: &Path) -> Result<()> {
|
||||
}
|
||||
|
||||
/// Extract tar archive with progress bar, handling whiteout files for OCI layers
|
||||
fn extract_with_progress<R: std::io::Read>(mut archive: tar::Archive<R>, dest: &Path, msg: &str) -> Result<()> {
|
||||
fn extract_with_progress<R: std::io::Read>(
|
||||
mut archive: tar::Archive<R>,
|
||||
dest: &Path,
|
||||
msg: &str,
|
||||
) -> Result<()> {
|
||||
let pb = ProgressBar::new_spinner();
|
||||
pb.set_style(ProgressStyle::default_spinner()
|
||||
pb.set_style(
|
||||
ProgressStyle::default_spinner()
|
||||
.template("{spinner:.green} {msg} ({pos} files)")
|
||||
.unwrap());
|
||||
.unwrap(),
|
||||
);
|
||||
pb.set_message(msg.to_string());
|
||||
|
||||
archive.set_preserve_permissions(true);
|
||||
archive.set_preserve_ownerships(false);
|
||||
archive.set_unpack_xattrs(false);
|
||||
|
||||
let entries = archive.entries()
|
||||
let entries = archive
|
||||
.entries()
|
||||
.context("Failed to read archive entries")?;
|
||||
|
||||
for entry in entries {
|
||||
@@ -269,7 +280,8 @@ fn extract_with_progress<R: std::io::Read>(mut archive: tar::Archive<R>, dest: &
|
||||
}
|
||||
// Do not extract the .wh.* marker itself
|
||||
} else {
|
||||
entry.unpack_in(dest)
|
||||
entry
|
||||
.unpack_in(dest)
|
||||
.with_context(|| format!("Failed to extract {}", path.display()))?;
|
||||
}
|
||||
|
||||
|
||||
+2
-6
@@ -1,5 +1,4 @@
|
||||
mod chroot;
|
||||
mod utils;
|
||||
mod cli;
|
||||
mod config;
|
||||
mod distro;
|
||||
@@ -9,6 +8,7 @@ mod mount;
|
||||
mod namespace;
|
||||
mod qemu;
|
||||
mod qemu_vm;
|
||||
mod utils;
|
||||
mod verbose;
|
||||
|
||||
/// Print to stderr only when --verbose / -v is active.
|
||||
@@ -160,11 +160,7 @@ fn main() -> Result<()> {
|
||||
}
|
||||
|
||||
/// Run in namespace/chroot mode
|
||||
fn namespace_mode(
|
||||
args: Args,
|
||||
rootfs: std::path::PathBuf,
|
||||
config: Config,
|
||||
) -> Result<()> {
|
||||
fn namespace_mode(args: Args, rootfs: std::path::PathBuf, config: Config) -> Result<()> {
|
||||
// Check user namespace availability
|
||||
namespace::check_user_namespace()?;
|
||||
|
||||
|
||||
+8
-2
@@ -459,13 +459,19 @@ mod tests {
|
||||
// Verify hostname format
|
||||
assert!(hostname.starts_with("ecr-test-"));
|
||||
assert!(hostname.len() > 9); // "ecr-test-" + at least 1 char
|
||||
assert!(hostname.chars().all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-'));
|
||||
assert!(hostname
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-'));
|
||||
|
||||
hostnames.insert(hostname);
|
||||
}
|
||||
|
||||
// With 100 iterations and good entropy, we should get many unique hostnames
|
||||
assert!(hostnames.len() > 50, "Expected many unique hostnames, got {}", hostnames.len());
|
||||
assert!(
|
||||
hostnames.len() > 50,
|
||||
"Expected many unique hostnames, got {}",
|
||||
hostnames.len()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+46
-20
@@ -55,7 +55,10 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
||||
Ubuntu/Debian: sudo apt install qemu-system-{}\n\
|
||||
Arch: sudo pacman -S qemu-system-{}\n\
|
||||
Alpine: sudo apk add qemu-system-{}",
|
||||
qemu_bin, get_arch_package_suffix(&config.arch), get_arch_package_suffix(&config.arch), get_arch_package_suffix(&config.arch)
|
||||
qemu_bin,
|
||||
get_arch_package_suffix(&config.arch),
|
||||
get_arch_package_suffix(&config.arch),
|
||||
get_arch_package_suffix(&config.arch)
|
||||
))?;
|
||||
|
||||
// Check if we can use KVM acceleration
|
||||
@@ -71,11 +74,15 @@ pub fn launch_qemu(config: QemuConfig) -> Result<()> {
|
||||
|
||||
// Generate a unique hostname like "ecr-vm-a1b2c3"
|
||||
// Use VM_HOSTNAME_SUFFIX_BITS constant for entropy
|
||||
let hostname_suffix = format!("{:x}", (std::process::id() as u64)
|
||||
.wrapping_mul(std::time::SystemTime::now()
|
||||
let hostname_suffix = format!(
|
||||
"{:x}",
|
||||
(std::process::id() as u64).wrapping_mul(
|
||||
std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_nanos() as u64) % crate::utils::VM_HOSTNAME_SUFFIX_BITS);
|
||||
.as_nanos() as u64
|
||||
) % crate::utils::VM_HOSTNAME_SUFFIX_BITS
|
||||
);
|
||||
let hostname = format!("ecr-vm-{}", hostname_suffix);
|
||||
|
||||
// Build kernel command line
|
||||
@@ -227,9 +234,11 @@ fn create_initramfs(rootfs: &Path) -> Result<PathBuf> {
|
||||
|
||||
// Create progress bar
|
||||
let pb = ProgressBar::new_spinner();
|
||||
pb.set_style(ProgressStyle::default_spinner()
|
||||
pb.set_style(
|
||||
ProgressStyle::default_spinner()
|
||||
.template("{spinner:.green} {msg} ({pos} files)")
|
||||
.unwrap());
|
||||
.unwrap(),
|
||||
);
|
||||
pb.set_message("Creating initramfs...");
|
||||
|
||||
// Create the cpio archive with progress
|
||||
@@ -238,12 +247,15 @@ fn create_initramfs(rootfs: &Path) -> Result<PathBuf> {
|
||||
let file_count = pb.position();
|
||||
|
||||
// Write directly to file (no compression)
|
||||
std::fs::write(&initramfs_path, &cpio_data)
|
||||
.context("Failed to write initramfs file")?;
|
||||
std::fs::write(&initramfs_path, &cpio_data).context("Failed to write initramfs file")?;
|
||||
|
||||
// Finish progress bar
|
||||
pb.finish_and_clear();
|
||||
veprintln!("Initramfs created: {} bytes, {} files", total_bytes, file_count);
|
||||
veprintln!(
|
||||
"Initramfs created: {} bytes, {} files",
|
||||
total_bytes,
|
||||
file_count
|
||||
);
|
||||
|
||||
Ok(initramfs_path)
|
||||
}
|
||||
@@ -278,12 +290,12 @@ fn create_cpio_archive(rootfs: &Path, pb: &ProgressBar) -> Result<Vec<u8>> {
|
||||
let mut writer = builder.write(&mut archive, file_size);
|
||||
|
||||
// Write the file content
|
||||
writer.write_all(data)
|
||||
writer
|
||||
.write_all(data)
|
||||
.context("Failed to write file content to cpio archive")?;
|
||||
|
||||
// Finish this entry (returns the underlying writer)
|
||||
writer.finish()
|
||||
.context("Failed to finish cpio entry")?;
|
||||
writer.finish().context("Failed to finish cpio entry")?;
|
||||
}
|
||||
|
||||
// Add essential device nodes for serial console
|
||||
@@ -314,7 +326,8 @@ fn create_cpio_archive(rootfs: &Path, pb: &ProgressBar) -> Result<Vec<u8>> {
|
||||
|
||||
// Device nodes have zero size
|
||||
let writer = builder.write(&mut archive, 0);
|
||||
writer.finish()
|
||||
writer
|
||||
.finish()
|
||||
.context("Failed to finish device node entry")?;
|
||||
}
|
||||
|
||||
@@ -371,14 +384,15 @@ fi
|
||||
.mtime(0);
|
||||
|
||||
let mut init_writer = init_builder.write(&mut archive, init_data.len() as u32);
|
||||
init_writer.write_all(init_data)
|
||||
init_writer
|
||||
.write_all(init_data)
|
||||
.context("Failed to write init script to cpio archive")?;
|
||||
init_writer.finish()
|
||||
init_writer
|
||||
.finish()
|
||||
.context("Failed to finish init script entry")?;
|
||||
|
||||
// Write the trailer (takes ownership and returns the writer)
|
||||
archive = newc::trailer(archive)
|
||||
.context("Failed to write cpio trailer")?;
|
||||
archive = newc::trailer(archive).context("Failed to write cpio trailer")?;
|
||||
|
||||
Ok(archive)
|
||||
}
|
||||
@@ -398,7 +412,11 @@ fn collect_entries(
|
||||
let dir_entries: Vec<_> = match std::fs::read_dir(current) {
|
||||
Ok(entries) => entries.collect::<std::result::Result<_, _>>()?,
|
||||
Err(e) => {
|
||||
veprintln!("Warning: cannot read directory {}: {}", current.display(), e);
|
||||
veprintln!(
|
||||
"Warning: cannot read directory {}: {}",
|
||||
current.display(),
|
||||
e
|
||||
);
|
||||
return Ok(entries);
|
||||
}
|
||||
};
|
||||
@@ -410,7 +428,11 @@ fn collect_entries(
|
||||
let metadata = match std::fs::symlink_metadata(&path) {
|
||||
Ok(m) => m,
|
||||
Err(e) => {
|
||||
veprintln!("Warning: skipping {} due to metadata error: {}", path.display(), e);
|
||||
veprintln!(
|
||||
"Warning: skipping {} due to metadata error: {}",
|
||||
path.display(),
|
||||
e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
@@ -495,7 +517,11 @@ fn collect_entries(
|
||||
|
||||
// Only print summary for the root directory
|
||||
if current == base {
|
||||
veprintln!("Collected {} entries, {} bytes total data", entries.len(), total_data);
|
||||
veprintln!(
|
||||
"Collected {} entries, {} bytes total data",
|
||||
entries.len(),
|
||||
total_data
|
||||
);
|
||||
}
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
+1
-5
@@ -196,11 +196,7 @@ pub fn validate_memory_string(s: &str) -> Result<()> {
|
||||
let suffix = s.chars().last().unwrap();
|
||||
let has_suffix = suffix.is_ascii_alphabetic();
|
||||
|
||||
let numeric_part = if has_suffix {
|
||||
&s[..s.len() - 1]
|
||||
} else {
|
||||
s
|
||||
};
|
||||
let numeric_part = if has_suffix { &s[..s.len() - 1] } else { s };
|
||||
|
||||
// Check for negative numbers
|
||||
if numeric_part.starts_with('-') {
|
||||
|
||||
Reference in New Issue
Block a user