Skip to content

Commit

Permalink
container/commit: Autoclean directories, also handle /run
Browse files Browse the repository at this point in the history
The original command here was just scoped to `/var`, but we also
don't want content in `/run`.  Extend the tooling to handle that.

Also, let's be a bit nicer here and auto-clean empty directories.

I was testing out the
https://github.com/coreos/coreos-layering-examples/blob/main/tailscale/Dockerfile
example and today we have this:

```
drwxr-xr-x root/root         0 2022-09-13 18:53 run/
drwxr-xr-x root/root         0 2022-09-13 18:51 run/rpm-ostree/
drwxr-xr-x root/root         0 2022-09-13 18:53 run/rpm-ostree/lock/
drwxr-xr-x root/root         0 2022-09-13 18:51 run/systemd/
drwxr-xr-x root/root         0 2022-09-13 18:51 run/systemd/resolve/
-rwx------ root/root         0 2022-09-13 18:51 run/systemd/resolve/stub-resolv.conf
...
drwxr-xr-x root/root         0 2022-09-13 18:53 var/
drwxr-xr-x root/root         0 2022-09-13 18:53 var/cache/
drwx------ root/root         0 2022-09-13 18:53 var/cache/ldconfig/
-rw------- root/root     22000 2022-09-13 18:53 var/cache/ldconfig/aux-cache
drwxr-xr-x root/root         0 2022-09-08 23:10 var/cache/tailscale/
drwxr-xr-x root/root         0 2022-09-13 18:53 var/tmp/
```

In this set, we can auto-clean the leftover locking directories
rpm-ostree (erroneously) leaves in `/run`.

I am tempted to auto-cleanup the `stub-resolv.conf` thing and the
`ldconfig/aux-cache`.
  • Loading branch information
cgwalters committed Sep 13, 2022
1 parent f99c7fe commit 35d87ad
Showing 1 changed file with 49 additions and 15 deletions.
64 changes: 49 additions & 15 deletions lib/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ use camino::Utf8PathBuf;
use std::fs;
use tokio::task;

/// Check if there are any files that are not directories and error out if
/// we find any, /var should not contain any files to commit in a container
/// as it is where we expect user data to reside.
fn validate_directories_only_recurse(path: &Utf8Path, error_count: &mut i32) -> Result<()> {
let context = || format!("Validating file: {:?}", path);
/// Gather count of non-empty directories. Empty directories are removed.
fn process_dir_recurse(path: &Utf8Path, error_count: &mut i32) -> Result<bool> {
let context = || format!("Validating: {path}");
let mut validated = true;
for entry in fs::read_dir(path).with_context(context)? {
let entry = entry?;
let path = entry.path();
Expand All @@ -23,30 +22,45 @@ fn validate_directories_only_recurse(path: &Utf8Path, error_count: &mut i32) ->
let metadata = path.symlink_metadata()?;

if metadata.is_dir() {
validate_directories_only_recurse(&path, error_count)?;
if !process_dir_recurse(&path, error_count)? {
validated = false;
}
} else {
validated = false;
*error_count += 1;
if *error_count < 20 {
eprintln!("Found file: {:?}", path)
}
}
}
Ok(())
if validated {
fs::remove_dir(path).with_context(context)?;
}
Ok(validated)
}

fn validate_ostree_compatibility_in(root: &Utf8Path) -> Result<()> {
let var_path = root.join("var");
println!("Checking /var for files");
/// Given a root filesystem, clean out empty directories and warn about
/// files in /run and /var.
fn prepare_ostree_commit_in(root: &Utf8Path) -> Result<()> {
let mut error_count = 0;
validate_directories_only_recurse(&var_path, &mut error_count)?;
let mut nonempty_paths = Vec::new();
for pathname in ["run", "var"] {
let path = root.join(pathname);
if path.exists() {
if !process_dir_recurse(&path, &mut error_count)? {
nonempty_paths.push(pathname);
}
}
}
if error_count != 0 {
anyhow::bail!("Found content in {var_path}");
let paths = nonempty_paths.join(" ");
anyhow::bail!("Found content in {paths}");
}
Ok(())
}

fn validate_ostree_compatibility() -> Result<()> {
validate_ostree_compatibility_in(Utf8Path::new("/"))
prepare_ostree_commit_in(Utf8Path::new("/"))
}

/// Entrypoint to the commit procedures, initially we just
Expand All @@ -67,14 +81,34 @@ mod tests {
let td = td.path();
let td = Utf8Path::from_path(td).unwrap();

// Handle the empty case
prepare_ostree_commit_in(td).unwrap();

let var = td.join("var");
let run = td.join("run");

std::fs::create_dir(&var)?;
validate_ostree_compatibility_in(td).unwrap();
assert!(var.exists());
prepare_ostree_commit_in(td).unwrap();
assert!(!var.exists());

let systemd = run.join("systemd");
std::fs::create_dir_all(&systemd)?;
prepare_ostree_commit_in(td).unwrap();
assert!(!var.exists());
assert!(!run.exists());

std::fs::create_dir(&var)?;
std::fs::write(var.join("foo"), "somefile")?;
assert!(prepare_ostree_commit_in(td).is_err());
assert!(var.exists());

assert!(validate_ostree_compatibility_in(td).is_err());
let nested = td.join("var/lib/nested");
std::fs::create_dir_all(&nested)?;
std::fs::write(nested.join("foo"), "test1")?;
std::fs::write(nested.join("foo2"), "test2")?;
assert!(prepare_ostree_commit_in(td).is_err());
assert!(var.exists());

Ok(())
}
Expand Down

0 comments on commit 35d87ad

Please sign in to comment.