From 2af95bc536cf79eefaed7dcf3757667adf6ac8e5 Mon Sep 17 00:00:00 2001 From: bin Date: Tue, 30 Nov 2021 22:14:54 +0800 Subject: [PATCH] agent: create directories for watchable-bind mounts In function `update_target`, if the updated source is a directory, we should create the corresponding directory. Fixes: #3140 Signed-off-by: bin --- src/agent/rustjail/src/mount.rs | 2 +- src/agent/src/watcher.rs | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/agent/rustjail/src/mount.rs b/src/agent/rustjail/src/mount.rs index 7de987400e..37370778a3 100644 --- a/src/agent/rustjail/src/mount.rs +++ b/src/agent/rustjail/src/mount.rs @@ -777,7 +777,7 @@ fn mount_from( let _ = fs::create_dir_all(&dir).map_err(|e| { log_child!( cfd_log, - "creat dir {}: {}", + "create dir {}: {}", dir.to_str().unwrap(), e.to_string() ) diff --git a/src/agent/src/watcher.rs b/src/agent/src/watcher.rs index b3cd3f832b..2476ac23c4 100644 --- a/src/agent/src/watcher.rs +++ b/src/agent/src/watcher.rs @@ -109,11 +109,12 @@ impl Storage { // if we are creating a directory: just create it, nothing more to do if source_file_path.symlink_metadata()?.file_type().is_dir() { - fs::create_dir_all(source_file_path) + let dest_file_path = self.make_target_path(&source_file_path)?; + + fs::create_dir_all(&dest_file_path) .await - .with_context(|| { - format!("Unable to mkdir all for {}", source_file_path.display()) - })? + .with_context(|| format!("Unable to mkdir all for {}", dest_file_path.display()))?; + return Ok(()); } // Assume we are dealing with either a file or a symlink now: @@ -922,7 +923,7 @@ mod tests { .file_type() .is_symlink()); assert_eq!(fs::read_link(&dst_symlink_file).unwrap(), src_file); - assert_eq!(fs::read_to_string(&dst_symlink_file).unwrap(), "foo") + assert_eq!(fs::read_to_string(&dst_symlink_file).unwrap(), "foo"); } #[tokio::test] @@ -1076,6 +1077,10 @@ mod tests { fs::create_dir_all(source_dir.path().join("A/B")).unwrap(); fs::write(source_dir.path().join("A/B/1.txt"), "two").unwrap(); + // A/C is an empty directory + let empty_dir = "A/C"; + fs::create_dir_all(source_dir.path().join(empty_dir)).unwrap(); + // delay 20 ms between writes to files in order to ensure filesystem timestamps are unique thread::sleep(Duration::from_millis(20)); @@ -1091,7 +1096,10 @@ mod tests { let logger = slog::Logger::root(slog::Discard, o!()); - assert_eq!(entry.scan(&logger).await.unwrap(), 5); + assert_eq!(entry.scan(&logger).await.unwrap(), 6); + + // check empty directory + assert!(dest_dir.path().join(empty_dir).exists()); // Should copy no files since nothing is changed since last check assert_eq!(entry.scan(&logger).await.unwrap(), 0); @@ -1112,6 +1120,12 @@ mod tests { // Update another file fs::write(source_dir.path().join("1.txt"), "updated").unwrap(); assert_eq!(entry.scan(&logger).await.unwrap(), 1); + + // create another empty directory A/C/D + let empty_dir = "A/C/D"; + fs::create_dir_all(source_dir.path().join(empty_dir)).unwrap(); + assert_eq!(entry.scan(&logger).await.unwrap(), 1); + assert!(dest_dir.path().join(empty_dir).exists()); } #[tokio::test]