A library for writing host-specific, single-binary configuration management and deployment tools
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

74 lines
1.6 KiB

8 years ago
8 years ago
5 years ago
8 years ago
5 years ago
5 years ago
7 years ago
8 years ago
8 years ago
8 years ago
5 years ago
5 years ago
8 years ago
5 years ago
5 years ago
8 years ago
  1. use crate::command_runner::CommandRunner;
  2. use crate::symbols::Symbol;
  3. use async_trait::async_trait;
  4. use std::error::Error;
  5. #[derive(Debug)]
  6. pub struct User<U, C> {
  7. user_name: U,
  8. command_runner: C,
  9. }
  10. impl<U, C> User<U, C> {
  11. pub fn new(user_name: U, command_runner: C) -> Self {
  12. Self {
  13. user_name,
  14. command_runner,
  15. }
  16. }
  17. }
  18. #[async_trait(?Send)]
  19. impl<U: AsRef<str>, C: CommandRunner> Symbol for User<U, C> {
  20. async fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
  21. let output = self
  22. .command_runner
  23. .run_with_args("getent", args!["passwd", self.user_name.as_ref()])
  24. .await?;
  25. match output.status.code() {
  26. Some(2) => Ok(false),
  27. Some(0) => Ok(true),
  28. _ => Err("Unknown error".into()),
  29. }
  30. }
  31. async fn execute(&self) -> Result<(), Box<dyn Error>> {
  32. self
  33. .command_runner
  34. .run_successfully(
  35. "adduser",
  36. args![
  37. // "-m", // Necessary for Fedora, not accepted in Debian
  38. "--system",
  39. self.user_name.as_ref(),
  40. ],
  41. )
  42. .await
  43. }
  44. }
  45. #[cfg(test)]
  46. mod test {
  47. use crate::async_utils::run;
  48. use crate::command_runner::StdCommandRunner;
  49. use crate::symbols::user::User;
  50. use crate::symbols::Symbol;
  51. #[test]
  52. fn test_target_reached_nonexisting() {
  53. let symbol = User {
  54. user_name: "nonexisting",
  55. command_runner: StdCommandRunner,
  56. };
  57. assert_eq!(run(symbol.target_reached()).unwrap(), false);
  58. }
  59. #[test]
  60. fn test_target_reached_root() {
  61. let symbol = User {
  62. user_name: "root",
  63. command_runner: StdCommandRunner,
  64. };
  65. assert_eq!(run(symbol.target_reached()).unwrap(), true);
  66. }
  67. }