New architecture
This commit is contained in:
parent
e4b3424ba6
commit
907a4962c5
61 changed files with 2742 additions and 3100 deletions
|
|
@ -1,97 +1,23 @@
|
|||
use std::borrow::Cow;
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use crate::command_runner::CommandRunner;
|
||||
use crate::resources::Resource;
|
||||
use crate::symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner};
|
||||
use crate::symbols::Symbol;
|
||||
use std::error::Error;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UserAdderError {
|
||||
AlreadyExists,
|
||||
UnknownError,
|
||||
ImplError(Box<dyn Error>),
|
||||
pub struct User<U, C> {
|
||||
user_name: U,
|
||||
command_runner: C,
|
||||
}
|
||||
|
||||
impl Error for UserAdderError {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
Self::AlreadyExists => "User already exists",
|
||||
Self::UnknownError => "Unknown error",
|
||||
Self::ImplError(_) => "User adding error",
|
||||
}
|
||||
}
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
Self::ImplError(ref e) => Some(e.as_ref()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for UserAdderError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.source() {
|
||||
Some(e) => write!(f, "{} (cause: {})", self.description(), e),
|
||||
None => write!(f, "{}", self.description()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait UserAdder {
|
||||
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError>;
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum UserError {
|
||||
GenericError,
|
||||
}
|
||||
|
||||
impl Error for UserError {
|
||||
fn description(&self) -> &str {
|
||||
match self {
|
||||
Self::GenericError => "Could not find out if user exists",
|
||||
}
|
||||
}
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match self {
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for UserError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.source() {
|
||||
Some(e) => write!(f, "{} (cause: {})", self.description(), e),
|
||||
None => write!(f, "{}", self.description()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct User<'a, C: CommandRunner, A: UserAdder> {
|
||||
user_name: Cow<'a, str>,
|
||||
command_runner: &'a C,
|
||||
user_adder: &'a A,
|
||||
}
|
||||
|
||||
impl<'a, C: CommandRunner, A: 'a + UserAdder> User<'a, C, A> {
|
||||
pub fn new(user_name: Cow<'a, str>, command_runner: &'a C, user_adder: &'a A) -> Self {
|
||||
User {
|
||||
impl<U, C> User<U, C> {
|
||||
pub fn new(user_name: U, command_runner: C) -> Self {
|
||||
Self {
|
||||
user_name,
|
||||
command_runner,
|
||||
user_adder,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, C: CommandRunner, A: 'a + UserAdder> fmt::Display for User<'a, C, A> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "User {}", self.user_name)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, C: CommandRunner, A: 'a + UserAdder> Symbol for User<'a, C, A> {
|
||||
impl<U: AsRef<str>, C: CommandRunner> Symbol for User<U, C> {
|
||||
fn target_reached(&self) -> Result<bool, Box<dyn Error>> {
|
||||
let output = self
|
||||
.command_runner
|
||||
|
|
@ -99,108 +25,34 @@ impl<'a, C: CommandRunner, A: 'a + UserAdder> Symbol for User<'a, C, A> {
|
|||
match output.status.code() {
|
||||
Some(2) => Ok(false),
|
||||
Some(0) => Ok(true),
|
||||
_ => Err(Box::new(UserError::GenericError)),
|
||||
_ => Err("Unknown error".into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn execute(&self) -> Result<(), Box<dyn Error>> {
|
||||
self
|
||||
.user_adder
|
||||
.add_user(self.user_name.as_ref())
|
||||
.map_err(|e| Box::new(e) as Box<dyn Error>)
|
||||
}
|
||||
|
||||
fn provides(&self) -> Option<Vec<Resource>> {
|
||||
Some(vec![Resource::new("user", self.user_name.to_owned())])
|
||||
}
|
||||
|
||||
fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box<dyn Action + 'b> {
|
||||
Box::new(SymbolAction::new(runner, self))
|
||||
}
|
||||
|
||||
fn into_action<'b>(self: Box<Self>, runner: &'b dyn SymbolRunner) -> Box<dyn Action + 'b>
|
||||
where
|
||||
Self: 'b,
|
||||
{
|
||||
Box::new(OwnedSymbolAction::new(runner, *self))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SystemUserAdder<'a, C: CommandRunner> {
|
||||
command_runner: &'a C,
|
||||
}
|
||||
|
||||
impl<'a, C: CommandRunner> SystemUserAdder<'a, C> {
|
||||
pub fn new(command_runner: &'a C) -> Self {
|
||||
SystemUserAdder { command_runner }
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: CommandRunner> UserAdder for SystemUserAdder<'_, C> {
|
||||
fn add_user(&self, user_name: &str) -> Result<(), UserAdderError> {
|
||||
let output = self.command_runner.run_with_args(
|
||||
self.command_runner.run_successfully(
|
||||
"adduser",
|
||||
args![
|
||||
// "-m", // Necessary for Fedora, not accepted in Debian
|
||||
"--system", user_name,
|
||||
"--system",
|
||||
self.user_name.as_ref(),
|
||||
],
|
||||
);
|
||||
match output {
|
||||
Ok(output) => match output.status.code() {
|
||||
Some(0) => Ok(()),
|
||||
Some(1) => {
|
||||
println!("{:?}", output);
|
||||
Err(UserAdderError::AlreadyExists)
|
||||
}
|
||||
_ => {
|
||||
println!("{:?}", output);
|
||||
Err(UserAdderError::UnknownError)
|
||||
}
|
||||
},
|
||||
Err(e) => Err(UserAdderError::ImplError(Box::new(e))),
|
||||
}
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
|
||||
use crate::command_runner::StdCommandRunner;
|
||||
use crate::symbols::user::User;
|
||||
use crate::symbols::user::UserAdder;
|
||||
use crate::symbols::user::UserAdderError;
|
||||
use crate::symbols::Symbol;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct DummyError;
|
||||
impl Error for DummyError {
|
||||
fn description(&self) -> &str {
|
||||
"DummyError"
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for DummyError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "DummyError")
|
||||
}
|
||||
}
|
||||
|
||||
struct DummyUserAdder;
|
||||
|
||||
impl UserAdder for DummyUserAdder {
|
||||
fn add_user(&self, _user_name: &str) -> Result<(), UserAdderError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_target_reached_nonexisting() {
|
||||
let symbol = User {
|
||||
user_name: "nonexisting".into(),
|
||||
command_runner: &StdCommandRunner,
|
||||
user_adder: &DummyUserAdder,
|
||||
user_name: "nonexisting",
|
||||
command_runner: StdCommandRunner,
|
||||
};
|
||||
assert_eq!(symbol.target_reached().unwrap(), false);
|
||||
}
|
||||
|
|
@ -208,9 +60,8 @@ mod test {
|
|||
#[test]
|
||||
fn test_target_reached_root() {
|
||||
let symbol = User {
|
||||
user_name: "root".into(),
|
||||
command_runner: &StdCommandRunner,
|
||||
user_adder: &DummyUserAdder,
|
||||
user_name: "root",
|
||||
command_runner: StdCommandRunner,
|
||||
};
|
||||
assert_eq!(symbol.target_reached().unwrap(), true);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue