-
-
Notifications
You must be signed in to change notification settings - Fork 626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[remoting] Move local process execution tempdirs into the workdir, add option to not delete them #6023
[remoting] Move local process execution tempdirs into the workdir, add option to not delete them #6023
Changes from all commits
edeb22f
c31192f
8f5a7f3
0ee311c
f8df958
a4fb6a1
b042acf
442ec72
827ce40
17f6142
7ac6a95
bbceb29
9a52d30
40f8c27
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
extern crate log; | ||
extern crate tempfile; | ||
|
||
use boxfuture::{BoxFuture, Boxable}; | ||
|
@@ -17,11 +18,23 @@ use bytes::Bytes; | |
pub struct CommandRunner { | ||
store: fs::Store, | ||
fs_pool: Arc<fs::ResettablePool>, | ||
work_dir: PathBuf, | ||
cleanup_local_dirs: bool, | ||
} | ||
|
||
impl CommandRunner { | ||
pub fn new(store: fs::Store, fs_pool: Arc<fs::ResettablePool>) -> CommandRunner { | ||
CommandRunner { store, fs_pool } | ||
pub fn new( | ||
store: fs::Store, | ||
fs_pool: Arc<fs::ResettablePool>, | ||
work_dir: PathBuf, | ||
cleanup_local_dirs: bool, | ||
) -> CommandRunner { | ||
CommandRunner { | ||
store, | ||
fs_pool, | ||
work_dir, | ||
cleanup_local_dirs, | ||
} | ||
} | ||
|
||
fn construct_output_snapshot( | ||
|
@@ -78,7 +91,7 @@ impl super::CommandRunner for CommandRunner { | |
let workdir = try_future!( | ||
tempfile::Builder::new() | ||
.prefix("process-execution") | ||
.tempdir() | ||
.tempdir_in(&self.work_dir) | ||
.map_err(|err| { | ||
format!( | ||
"Error making tempdir for local process execution: {:?}", | ||
|
@@ -92,7 +105,9 @@ impl super::CommandRunner for CommandRunner { | |
let env = req.env; | ||
let output_file_paths = req.output_files; | ||
let output_dir_paths = req.output_directories; | ||
let cleanup_local_dirs = self.cleanup_local_dirs; | ||
let argv = req.argv; | ||
let req_description = req.description; | ||
self | ||
.store | ||
.materialize_directory(workdir.path().to_owned(), req.input_files) | ||
|
@@ -109,7 +124,7 @@ impl super::CommandRunner for CommandRunner { | |
.map_err(|e| format!("Error executing process: {:?}", e)) | ||
.map(|output| (output, workdir)) | ||
}) | ||
.and_then(|(output, workdir)| { | ||
.and_then(move |(output, workdir)| { | ||
let output_snapshot = if output_file_paths.is_empty() && output_dir_paths.is_empty() { | ||
future::ok(fs::Snapshot::empty()).to_boxed() | ||
} else { | ||
|
@@ -137,8 +152,20 @@ impl super::CommandRunner for CommandRunner { | |
) | ||
}) | ||
// Force workdir not to get dropped until after we've ingested the outputs | ||
.map(|result| (result, workdir)) | ||
.map(|(result, _workdir)| result) | ||
.map(move |result| (result, workdir) ) | ||
.map(move |(result, workdir)| { | ||
if !cleanup_local_dirs { | ||
// This consumes the `TempDir` without deleting directory on the filesystem, meaning | ||
// that the temporary directory will no longer be automatically deleted when dropped. | ||
let preserved_path = workdir.into_path(); | ||
info!( | ||
"preserved local process execution dir `{:?}` for {:?}", | ||
preserved_path, | ||
req_description | ||
); | ||
} | ||
result | ||
}) | ||
.to_boxed() | ||
}; | ||
|
||
|
@@ -328,7 +355,7 @@ mod tests { | |
|
||
#[test] | ||
fn output_files_one() { | ||
let result = run_command_locally_in_dir(ExecuteProcessRequest { | ||
let result = run_command_locally(ExecuteProcessRequest { | ||
argv: vec![ | ||
find_bash(), | ||
"-c".to_owned(), | ||
|
@@ -355,7 +382,7 @@ mod tests { | |
|
||
#[test] | ||
fn output_dirs() { | ||
let result = run_command_locally_in_dir(ExecuteProcessRequest { | ||
let result = run_command_locally(ExecuteProcessRequest { | ||
argv: vec![ | ||
find_bash(), | ||
"-c".to_owned(), | ||
|
@@ -387,7 +414,7 @@ mod tests { | |
|
||
#[test] | ||
fn output_files_many() { | ||
let result = run_command_locally_in_dir(ExecuteProcessRequest { | ||
let result = run_command_locally(ExecuteProcessRequest { | ||
argv: vec![ | ||
find_bash(), | ||
"-c".to_owned(), | ||
|
@@ -420,7 +447,7 @@ mod tests { | |
|
||
#[test] | ||
fn output_files_execution_failure() { | ||
let result = run_command_locally_in_dir(ExecuteProcessRequest { | ||
let result = run_command_locally(ExecuteProcessRequest { | ||
argv: vec![ | ||
find_bash(), | ||
"-c".to_owned(), | ||
|
@@ -451,7 +478,7 @@ mod tests { | |
|
||
#[test] | ||
fn output_files_partial_output() { | ||
let result = run_command_locally_in_dir(ExecuteProcessRequest { | ||
let result = run_command_locally(ExecuteProcessRequest { | ||
argv: vec![ | ||
find_bash(), | ||
"-c".to_owned(), | ||
|
@@ -478,21 +505,68 @@ mod tests { | |
) | ||
} | ||
|
||
#[test] | ||
fn test_directory_preservation() { | ||
let preserved_work_tmpdir = TempDir::new().unwrap(); | ||
let preserved_work_root = preserved_work_tmpdir.path().to_owned(); | ||
|
||
let result = run_command_locally_in_dir( | ||
ExecuteProcessRequest { | ||
argv: vec![ | ||
find_bash(), | ||
"-c".to_owned(), | ||
format!("echo -n {} > {}", TestData::roland().string(), "roland"), | ||
], | ||
env: BTreeMap::new(), | ||
input_files: fs::EMPTY_DIGEST, | ||
output_files: vec![PathBuf::from("roland")].into_iter().collect(), | ||
output_directories: BTreeSet::new(), | ||
timeout: Duration::from_millis(1000), | ||
description: "bash".to_string(), | ||
}, | ||
preserved_work_root.clone(), | ||
false, | ||
); | ||
result.unwrap(); | ||
|
||
assert_eq!(preserved_work_root.exists(), true); | ||
|
||
// Collect all of the top level sub-dirs under our test workdir. | ||
let subdirs = testutil::file::list_dir(&preserved_work_root); | ||
assert_eq!(subdirs.len(), 1); | ||
|
||
// Then look for a file like e.g. `/tmp/abc1234/process-execution7zt4pH/roland` | ||
let rolands_path = preserved_work_root.join(&subdirs[0]).join("roland"); | ||
assert_eq!(rolands_path.exists(), true); | ||
} | ||
|
||
fn run_command_locally( | ||
req: ExecuteProcessRequest, | ||
) -> Result<FallibleExecuteProcessResult, String> { | ||
run_command_locally_in_dir(req) | ||
let work_dir = TempDir::new().unwrap(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This function is interesting now... For how this is used today, this is fine, but may be worth a comment for the future. Or maybe not :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, completely intentional for this variant of the helper based on how it's being used. |
||
run_command_locally_in_dir_with_cleanup(req, work_dir.path().to_owned()) | ||
} | ||
|
||
fn run_command_locally_in_dir_with_cleanup( | ||
req: ExecuteProcessRequest, | ||
dir: PathBuf, | ||
) -> Result<FallibleExecuteProcessResult, String> { | ||
run_command_locally_in_dir(req, dir, true) | ||
} | ||
|
||
fn run_command_locally_in_dir( | ||
req: ExecuteProcessRequest, | ||
dir: PathBuf, | ||
cleanup: bool, | ||
) -> Result<FallibleExecuteProcessResult, String> { | ||
let store_dir = TempDir::new().unwrap(); | ||
let pool = Arc::new(fs::ResettablePool::new("test-pool-".to_owned())); | ||
let store = fs::Store::local_only(store_dir.path(), pool.clone()).unwrap(); | ||
let runner = super::CommandRunner { | ||
store: store, | ||
fs_pool: pool, | ||
work_dir: dir, | ||
cleanup_local_dirs: cleanup, | ||
}; | ||
runner.run(req).wait() | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a
testutil::file::list_dir
which may be useful hereThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done