Skip to content

Commit 17d344d

Browse files
committed
fix: krane using lazy_static! caused uncleaned temp files
1 parent e4fb9f4 commit 17d344d

File tree

4 files changed

+86
-38
lines changed

4 files changed

+86
-38
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/krane/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ publish = false
99
[dependencies]
1010
anyhow.workspace = true
1111
include-env-compressed.workspace = true
12-
lazy_static.workspace = true
12+
sha2.workspace = true
13+
14+
[dev-dependencies]
1315
tempfile.workspace = true
1416

1517
[build-dependencies]

tools/krane/src/lib.rs

Lines changed: 77 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,106 @@
11
use anyhow::Result;
22
use include_env_compressed::{include_archive_from_env, Archive};
3-
use std::fs::{File, Permissions};
3+
use sha2::{Digest, Sha256};
4+
use std::fs;
45
use std::os::unix::fs::PermissionsExt;
5-
use std::path::PathBuf;
6-
7-
use tempfile::TempDir;
86

97
pub const KRANE_BIN: Archive = include_archive_from_env!("KRANE_PATH");
108

11-
lazy_static::lazy_static! {
12-
pub static ref KRANE: Krane = Krane::seal().unwrap();
9+
fn expected_checksum() -> String {
10+
let mut hasher = Sha256::new();
11+
let mut reader = KRANE_BIN.reader();
12+
std::io::copy(&mut reader, &mut hasher).unwrap();
13+
format!("{:x}", hasher.finalize())
1314
}
1415

15-
#[derive(Debug)]
16-
pub struct Krane {
17-
// Hold the file in memory to keep the fd open
18-
_tmp_dir: TempDir,
19-
path: PathBuf,
16+
fn file_checksum(path: &std::path::Path) -> Result<String> {
17+
let mut hasher = Sha256::new();
18+
let mut file = fs::File::open(path)?;
19+
std::io::copy(&mut file, &mut hasher)?;
20+
Ok(format!("{:x}", hasher.finalize()))
2021
}
2122

22-
impl Krane {
23-
fn seal() -> Result<Krane> {
24-
let tmp_dir = TempDir::new()?;
25-
let path = tmp_dir.path().join("krane");
23+
pub fn ensure_krane_in_dir(tools_dir: impl AsRef<std::path::Path>) -> Result<std::path::PathBuf> {
24+
let tools_dir = tools_dir.as_ref();
25+
let krane_path = tools_dir.join("krane");
2626

27-
let mut krane_file = File::create(&path)?;
28-
let permissions = Permissions::from_mode(0o755);
29-
krane_file.set_permissions(permissions)?;
27+
let needs_update = if krane_path.exists() {
28+
match file_checksum(&krane_path) {
29+
Ok(actual) => actual != expected_checksum(),
30+
Err(_) => true, // If we can't read it, assume it needs update
31+
}
32+
} else {
33+
true
34+
};
3035

31-
let mut krane_reader = KRANE_BIN.reader();
36+
if needs_update {
37+
fs::create_dir_all(tools_dir)?;
3238

33-
std::io::copy(&mut krane_reader, &mut krane_file)?;
39+
let temp_path = tools_dir.join(format!(".krane.tmp.{}", std::process::id()));
3440

35-
Ok(Krane {
36-
_tmp_dir: tmp_dir,
37-
path,
38-
})
39-
}
41+
{
42+
let mut temp_file = fs::File::create(&temp_path)?;
43+
let permissions = fs::Permissions::from_mode(0o755);
44+
temp_file.set_permissions(permissions)?;
45+
46+
let mut krane_reader = KRANE_BIN.reader();
47+
std::io::copy(&mut krane_reader, &mut temp_file)?;
48+
49+
use std::io::Write;
50+
temp_file.flush()?;
51+
}
4052

41-
pub fn path(&self) -> &PathBuf {
42-
&self.path
53+
fs::rename(temp_path, &krane_path)?;
4354
}
55+
56+
Ok(krane_path)
4457
}
4558

4659
#[cfg(test)]
4760
mod test {
4861
use super::*;
49-
use std::process::Command;
5062

5163
#[test]
52-
fn test_krane_runs() {
53-
let status = Command::new(KRANE.path())
64+
fn test_checksum_functions() {
65+
let checksum1 = expected_checksum();
66+
let checksum2 = expected_checksum();
67+
assert_eq!(checksum1, checksum2);
68+
assert!(!checksum1.is_empty());
69+
println!("Expected checksum: {}", checksum1);
70+
}
71+
72+
#[test]
73+
fn test_ensure_krane_in_dir() {
74+
use tempfile::TempDir;
75+
76+
let temp_dir = TempDir::new().unwrap();
77+
println!("Testing ensure_krane_in_dir in: {:?}", temp_dir.path());
78+
79+
let path1 = crate::ensure_krane_in_dir(temp_dir.path()).unwrap();
80+
assert!(path1.exists());
81+
assert!(path1.ends_with("krane"));
82+
println!("Created krane at: {:?}", path1);
83+
84+
let metadata = std::fs::metadata(&path1).unwrap();
85+
let permissions = metadata.permissions();
86+
assert!(permissions.mode() & 0o111 != 0);
87+
println!("File is executable: {}", permissions.mode() & 0o111 != 0);
88+
89+
let mtime1 = std::fs::metadata(&path1).unwrap().modified().unwrap();
90+
std::thread::sleep(std::time::Duration::from_millis(10));
91+
92+
let path2 = crate::ensure_krane_in_dir(temp_dir.path()).unwrap();
93+
let mtime2 = std::fs::metadata(&path2).unwrap().modified().unwrap();
94+
95+
assert_eq!(path1, path2);
96+
assert_eq!(mtime1, mtime2);
97+
println!("File was reused (same mtime): {}", mtime1 == mtime2);
98+
99+
let status = std::process::Command::new(&path1)
54100
.arg("--help")
55101
.output()
56102
.expect("failed to run krane");
57-
58103
assert_eq!(status.status.code().unwrap(), 0);
104+
println!("Krane binary works correctly");
59105
}
60106
}

tools/oci-cli-wrapper/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::{collections::HashMap, path::Path};
1717
use async_trait::async_trait;
1818
use cli::CommandLine;
1919
use crane::CraneCLI;
20-
use krane_bundle::KRANE;
20+
use krane_bundle::ensure_krane_in_dir;
2121
use olpc_cjson::CanonicalFormatter;
2222
use serde::{Deserialize, Serialize};
2323
use snafu::ResultExt;
@@ -31,12 +31,12 @@ pub struct ImageTool {
3131
}
3232

3333
impl ImageTool {
34-
/// Uses the builtin `krane` provided by the `tools/krane` crate.
3534
pub fn from_builtin_krane() -> Self {
35+
let tools_dir = std::path::Path::new("./build/tools");
36+
let krane_path = ensure_krane_in_dir(tools_dir).expect("Failed to setup krane binary");
37+
3638
let image_tool_impl = Box::new(CraneCLI {
37-
cli: CommandLine {
38-
path: KRANE.path().to_path_buf(),
39-
},
39+
cli: CommandLine { path: krane_path },
4040
});
4141
Self { image_tool_impl }
4242
}

0 commit comments

Comments
 (0)