fix(container): avoid detecting WSL as a systemd-container (#4593)

This commit is contained in:
David Knaack 2022-11-15 11:14:52 +01:00 committed by GitHub
parent 5f9804dd6a
commit b47a4fe514
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 129 additions and 45 deletions

View File

@ -10,7 +10,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
use super::ModuleConfig; use super::ModuleConfig;
use crate::configs::container::ContainerConfig; use crate::configs::container::ContainerConfig;
use crate::formatter::StringFormatter; use crate::formatter::StringFormatter;
use crate::utils::read_file; use crate::utils::{self, read_file};
pub fn container_name(context: &Context) -> Option<String> { pub fn container_name(context: &Context) -> Option<String> {
use crate::utils::context_path; use crate::utils::context_path;
@ -26,7 +26,14 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
return Some("OCI".into()); return Some("OCI".into());
} }
if context_path(context, "/run/systemd/container").exists() { // WSL with systemd will set the contents of this file to "wsl"
// Avoid showing the container module in that case
let systemd_path = context_path(context, "/run/systemd/container");
if utils::read_file(systemd_path)
.ok()
.filter(|s| s.trim() != "wsl")
.is_some()
{
// systemd // systemd
return Some("Systemd".into()); return Some("Systemd".into());
} }
@ -101,8 +108,9 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::test::ModuleRenderer; use crate::test::ModuleRenderer;
use crate::utils;
use nu_ansi_term::Color; use nu_ansi_term::Color;
use std::path::PathBuf; use std::fs;
#[test] #[test]
fn test_none_if_disabled() { fn test_none_if_disabled() {
@ -120,8 +128,6 @@ mod tests {
} }
fn containerenv(name: Option<&str>) -> std::io::Result<(Option<String>, Option<String>)> { fn containerenv(name: Option<&str>) -> std::io::Result<(Option<String>, Option<String>)> {
use std::io::Write;
let renderer = ModuleRenderer::new("container") let renderer = ModuleRenderer::new("container")
// For a custom config // For a custom config
.config(toml::toml! { .config(toml::toml! {
@ -131,18 +137,15 @@ mod tests {
let root_path = renderer.root_path(); let root_path = renderer.root_path();
let mut containerenv = PathBuf::from(root_path); let containerenv = root_path.join("run/.containerenv");
containerenv.push("run"); fs::create_dir_all(containerenv.parent().unwrap())?;
std::fs::DirBuilder::new()
.recursive(true)
.create(&containerenv)?;
containerenv.push(".containerenv"); let contents = match name {
let mut file = std::fs::File::create(&containerenv)?; Some(name) => format!("image=\"{name}\"\n"),
if let Some(name) = name { None => String::new(),
file.write_all(format!("image=\"{name}\"\n").as_bytes())?; };
} utils::write_file(&containerenv, contents)?;
// The output of the module // The output of the module
let actual = renderer let actual = renderer
@ -182,6 +185,73 @@ mod tests {
Ok(()) Ok(())
} }
#[test]
#[cfg(target_os = "linux")]
fn test_containerenv_systemd() -> std::io::Result<()> {
let renderer = ModuleRenderer::new("container")
// For a custom config
.config(toml::toml! {
[container]
disabled = false
});
let root_path = renderer.root_path();
let systemd_path = root_path.join("run/systemd/container");
fs::create_dir_all(systemd_path.parent().unwrap())?;
utils::write_file(&systemd_path, "systemd-nspawn\n")?;
// The output of the module
let actual = renderer
// Run the module and collect the output
.collect();
// The value that should be rendered by the module.
let expected = Some(format!(
"{} ",
Color::Red
.bold()
.dimmed()
.paint(format!("⬢ [{}]", "Systemd"))
));
// Assert that the actual and expected values are the same
assert_eq!(actual, expected);
Ok(())
}
#[test]
#[cfg(target_os = "linux")]
fn test_containerenv_wsl() -> std::io::Result<()> {
let renderer = ModuleRenderer::new("container")
// For a custom config
.config(toml::toml! {
[container]
disabled = false
});
let root_path = renderer.root_path();
let systemd_path = root_path.join("run/systemd/container");
fs::create_dir_all(systemd_path.parent().unwrap())?;
utils::write_file(&systemd_path, "wsl\n")?;
// The output of the module
let actual = renderer
// Run the module and collect the output
.collect();
// The value that should be rendered by the module.
let expected = None;
// Assert that the actual and expected values are the same
assert_eq!(actual, expected);
Ok(())
}
#[test] #[test]
#[cfg(not(target_os = "linux"))] #[cfg(not(target_os = "linux"))]

View File

@ -109,11 +109,11 @@ impl<'a> GitDiff<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::utils::create_command; use crate::utils::{create_command, write_file};
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{self, Error, ErrorKind, Write}; use std::io::{self, Error, ErrorKind, Write};
use std::path::{Path, PathBuf}; use std::path::Path;
use std::process::Stdio; use std::process::Stdio;
use nu_ansi_term::Color; use nu_ansi_term::Color;
@ -157,7 +157,7 @@ mod tests {
let path = repo_dir.path(); let path = repo_dir.path();
let file_path = path.join("the_file"); let file_path = path.join("the_file");
write_file(file_path, "First Line\nSecond Line")?; write_file(file_path, "First Line\nSecond Line\n")?;
let actual = render_metrics(path); let actual = render_metrics(path);
@ -173,7 +173,7 @@ mod tests {
let path = repo_dir.path(); let path = repo_dir.path();
let file_path = path.join("the_file"); let file_path = path.join("the_file");
write_file(file_path, "\nSecond Line\n\nModified\nAdded")?; write_file(file_path, "\nSecond Line\n\nModified\nAdded\n")?;
let actual = render_metrics(path); let actual = render_metrics(path);
@ -263,16 +263,6 @@ mod tests {
} }
} }
fn write_file(file: PathBuf, text: &str) -> io::Result<()> {
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(file)?;
writeln!(file, "{text}")?;
file.sync_all()
}
fn create_repo_with_commit() -> io::Result<tempfile::TempDir> { fn create_repo_with_commit() -> io::Result<tempfile::TempDir> {
let repo_dir = tempfile::tempdir()?; let repo_dir = tempfile::tempdir()?;
let path = repo_dir.path(); let path = repo_dir.path();
@ -312,7 +302,7 @@ mod tests {
)?; )?;
// Write a file on master and commit it // Write a file on master and commit it
write_file(file, "First Line\nSecond Line\nThird Line")?; write_file(file, "First Line\nSecond Line\nThird Line\n")?;
run_git_cmd(["add", "the_file"], Some(path), true)?; run_git_cmd(["add", "the_file"], Some(path), true)?;
run_git_cmd( run_git_cmd(
["commit", "--message", "Commit A", "--no-gpg-sign"], ["commit", "--message", "Commit A", "--no-gpg-sign"],

View File

@ -159,13 +159,12 @@ struct StateDescription<'a> {
mod tests { mod tests {
use nu_ansi_term::Color; use nu_ansi_term::Color;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs::OpenOptions; use std::io::{self, Error, ErrorKind};
use std::io::{self, Error, ErrorKind, Write};
use std::path::Path; use std::path::Path;
use std::process::Stdio; use std::process::Stdio;
use crate::test::ModuleRenderer; use crate::test::ModuleRenderer;
use crate::utils::create_command; use crate::utils::{create_command, write_file};
#[test] #[test]
fn show_nothing_on_empty_dir() -> io::Result<()> { fn show_nothing_on_empty_dir() -> io::Result<()> {
@ -289,15 +288,6 @@ mod tests {
let path = repo_dir.path(); let path = repo_dir.path();
let conflicted_file = repo_dir.path().join("the_file"); let conflicted_file = repo_dir.path().join("the_file");
let write_file = |text: &str| {
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&conflicted_file)?;
write!(file, "{text}")
};
// Initialize a new git repo // Initialize a new git repo
run_git_cmd( run_git_cmd(
[ [
@ -332,7 +322,7 @@ mod tests {
)?; )?;
// Write a file on master and commit it // Write a file on master and commit it
write_file("Version A")?; write_file(&conflicted_file, "Version A")?;
run_git_cmd(["add", "the_file"], Some(path), true)?; run_git_cmd(["add", "the_file"], Some(path), true)?;
run_git_cmd( run_git_cmd(
["commit", "--message", "Commit A", "--no-gpg-sign"], ["commit", "--message", "Commit A", "--no-gpg-sign"],
@ -342,7 +332,7 @@ mod tests {
// Switch to another branch, and commit a change to the file // Switch to another branch, and commit a change to the file
run_git_cmd(["checkout", "-b", "other-branch"], Some(path), true)?; run_git_cmd(["checkout", "-b", "other-branch"], Some(path), true)?;
write_file("Version B")?; write_file(&conflicted_file, "Version B")?;
run_git_cmd( run_git_cmd(
["commit", "--all", "--message", "Commit B", "--no-gpg-sign"], ["commit", "--all", "--message", "Commit B", "--no-gpg-sign"],
Some(path), Some(path),
@ -351,7 +341,7 @@ mod tests {
// Switch back to master, and commit a third change to the file // Switch back to master, and commit a third change to the file
run_git_cmd(["checkout", "master"], Some(path), true)?; run_git_cmd(["checkout", "master"], Some(path), true)?;
write_file("Version C")?; write_file(conflicted_file, "Version C")?;
run_git_cmd( run_git_cmd(
["commit", "--all", "--message", "Commit C", "--no-gpg-sign"], ["commit", "--all", "--message", "Commit C", "--no-gpg-sign"],
Some(path), Some(path),

View File

@ -48,6 +48,40 @@ pub fn read_file<P: AsRef<Path> + Debug>(file_name: P) -> Result<String> {
result result
} }
/// Write a string to a file
#[cfg(test)]
pub fn write_file<P: AsRef<Path>, S: AsRef<str>>(file_name: P, text: S) -> Result<()> {
use std::io::Write;
let file_name = file_name.as_ref();
let text = text.as_ref();
log::trace!("Trying to write {text:?} to {file_name:?}");
let mut file = match std::fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(file_name)
{
Ok(file) => file,
Err(err) => {
log::warn!("Error creating file: {:?}", err);
return Err(err);
}
};
match file.write_all(text.as_bytes()) {
Ok(_) => {
log::trace!("File {file_name:?} written successfully");
}
Err(err) => {
log::warn!("Error writing to file: {err:?}");
return Err(err);
}
}
file.sync_all()
}
/// Reads command output from stderr or stdout depending on to which stream program streamed it's output /// Reads command output from stderr or stdout depending on to which stream program streamed it's output
pub fn get_command_string_output(command: CommandOutput) -> String { pub fn get_command_string_output(command: CommandOutput) -> String {
if command.stdout.is_empty() { if command.stdout.is_empty() {