Why does it not compile?
This commit is contained in:
commit
74bfea3434
18 changed files with 1576 additions and 0 deletions
34
src/modules/package/apt.rs
Normal file
34
src/modules/package/apt.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
use crate::utils::cmd::Cmd;
|
||||
|
||||
use super::{PackageError, PackageList, SpecificPackageManager};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DebianPackageManager;
|
||||
|
||||
impl SpecificPackageManager for DebianPackageManager {
|
||||
fn name(&self) -> &'static str {
|
||||
"apt"
|
||||
}
|
||||
|
||||
fn update(&self) -> Result<(), PackageError> {
|
||||
let res = Cmd::new("apt").arg("update").run()?;
|
||||
|
||||
if ! res.success {
|
||||
return Err(PackageError::CmdFail(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn install(&self, list: PackageList) -> Result<(), PackageError> {
|
||||
let res = Cmd::new("apt").arg("install").args(list.list()).run()?;
|
||||
|
||||
if ! res.success {
|
||||
return Err(PackageError::CmdFail(res));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove(&self, _list: PackageList) -> Result<(), PackageError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
103
src/modules/package/builder.rs
Normal file
103
src/modules/package/builder.rs
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
use super::{PackageArgs, IntoPackageList, PackageList, PackageState, PackageModule, PackageStatus, PackageError, SpecificPackageManager};
|
||||
use super::apt::DebianPackageManager;
|
||||
use super::pacman::ArchlinuxPackageManager;
|
||||
use std::boxed::Box;
|
||||
|
||||
use crate::Module;
|
||||
|
||||
pub struct PackageArgsBuilder<Packages, State, Manager> {
|
||||
name: Packages,
|
||||
state: State,
|
||||
manager: Manager,
|
||||
}
|
||||
|
||||
pub struct NoPackage;
|
||||
pub struct NoState;
|
||||
pub struct NoManager;
|
||||
|
||||
impl PackageArgsBuilder<NoPackage, NoState, NoManager> {
|
||||
pub fn new() -> PackageArgsBuilder<NoPackage, NoState, NoManager> {
|
||||
PackageArgsBuilder {
|
||||
name: NoPackage,
|
||||
state: NoState,
|
||||
manager: NoManager,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<State, Manager> PackageArgsBuilder<NoPackage, State, Manager> {
|
||||
pub fn name<T: IntoPackageList>(self, list: T) -> PackageArgsBuilder<PackageList, State, Manager> {
|
||||
let Self { state, manager, .. } = self;
|
||||
|
||||
PackageArgsBuilder {
|
||||
name: list.into_package_list(),
|
||||
state,
|
||||
manager,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Packages, Manager> PackageArgsBuilder<Packages, NoState, Manager> {
|
||||
pub fn state(self, state: PackageState) -> PackageArgsBuilder<Packages, PackageState, Manager> {
|
||||
let Self { name, manager, .. } = self;
|
||||
|
||||
PackageArgsBuilder {
|
||||
name,
|
||||
state,
|
||||
manager,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Packages, State> PackageArgsBuilder<Packages, State, NoManager> {
|
||||
pub fn with(self, manager: impl SpecificPackageManager + 'static) -> PackageArgsBuilder<Packages, State, Box<dyn SpecificPackageManager>> {
|
||||
let Self { name, state, .. } = self;
|
||||
|
||||
PackageArgsBuilder {
|
||||
name,
|
||||
state,
|
||||
manager: Box::new(manager),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_apt(self) -> PackageArgsBuilder<Packages, State, Box<dyn SpecificPackageManager>> {
|
||||
let Self { name, state, .. } = self;
|
||||
PackageArgsBuilder {
|
||||
name,
|
||||
state,
|
||||
manager: Box::new(DebianPackageManager),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_pacman(self) -> PackageArgsBuilder<Packages, State, Box<dyn SpecificPackageManager>> {
|
||||
let Self { name, state, .. } = self;
|
||||
PackageArgsBuilder {
|
||||
name,
|
||||
state,
|
||||
manager: Box::new(ArchlinuxPackageManager),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// We can only RUN the args when a package manager has been set. Alternatively,
|
||||
// when called inside a playbook, the package manager can be populated automatically from facts.
|
||||
impl PackageArgsBuilder<PackageList, PackageState, Box<dyn SpecificPackageManager>> {
|
||||
pub fn run(self) -> Result<PackageStatus, PackageError> {
|
||||
self.build().run()
|
||||
}
|
||||
}
|
||||
|
||||
impl PackageArgsBuilder<PackageList, PackageState, Box<dyn SpecificPackageManager>> {
|
||||
pub fn build(self) -> PackageModule<Box<dyn SpecificPackageManager>> {
|
||||
let Self { name, state, manager, .. } = self;
|
||||
|
||||
PackageModule {
|
||||
args: PackageArgs {
|
||||
name,
|
||||
state,
|
||||
},
|
||||
manager,
|
||||
}
|
||||
}
|
||||
}
|
||||
110
src/modules/package/list.rs
Normal file
110
src/modules/package/list.rs
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::facts::{Facts, os::OsFamily};
|
||||
use crate::utils::cmd::CmdOutput;
|
||||
|
||||
use std::boxed::Box;
|
||||
|
||||
pub mod pacman;
|
||||
use pacman::ArchlinuxPackageManager;
|
||||
pub mod apt;
|
||||
use apt::DebianPackageManager;
|
||||
|
||||
pub mod builder;
|
||||
use builder::{NoPackage, PackageArgsBuilder};
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct PackageArgs {
|
||||
name: PackageList,
|
||||
state: PackageState,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum PackageState {
|
||||
Present,
|
||||
Absent,
|
||||
Latest,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PackageModule<Manager> {
|
||||
manager: Manager,
|
||||
args: PackageArgs,
|
||||
}
|
||||
|
||||
impl<Manager> Module<PackageArgs, (), PackageError> for PackageModule<Manager> {
|
||||
fn clone_args(&self) -> PackageArgs {
|
||||
self.args.clone()
|
||||
}
|
||||
|
||||
fn module_name() -> &'static str {
|
||||
"package"
|
||||
}
|
||||
}
|
||||
|
||||
impl Module<PackageArgs, (), PackageError> for PackageModule<Box<dyn SpecificPackageManager>> {
|
||||
fn run(&self) -> Result<(), PackageError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Module<PackageArgs, (), PackageError> for PackageModule<NoManager> {
|
||||
fn with_facts(self, facts: &Facts) -> PackageModule<Box<dyn SpecificPackageManager>> {
|
||||
let Self { args, .. } = self;
|
||||
|
||||
let manager = match facts.os.family() {
|
||||
OsFamily::Debian => Box::new(DebianPackageManager),
|
||||
OsFamily::Archlinux => Box::new(ArchlinuxPackageManager),
|
||||
};
|
||||
|
||||
PackageModule {
|
||||
args,
|
||||
manager,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PackageModule {
|
||||
pub fn new() -> PackageArgsBuilder {
|
||||
PackageArgsBuilder::new()
|
||||
}
|
||||
|
||||
pub fn from_args_with_facts(args: PackageArgs, facts: &Facts) -> PackageModule {
|
||||
let manager = match facts.os.family() {
|
||||
OsFamily::Debian => PackageModule(Box::new(DebianPackageManager)),
|
||||
OsFamily::Archlinux => PackageModule(Box::new(ArchlinuxPackageManager)),
|
||||
};
|
||||
PackageModule {
|
||||
manager,
|
||||
args,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_args_with(args: PackageArgs, manager: SpecificPackageManager) -> PackageManager {
|
||||
PackageModule {
|
||||
manager: Box::new(manager),
|
||||
args,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum PackageError {
|
||||
IoError(String),
|
||||
CmdFail(CmdOutput),
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for PackageError {
|
||||
fn from(e: std::io::Error) -> PackageError {
|
||||
PackageError::IoError(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SpecificPackageManager: std::fmt::Debug {
|
||||
fn name(&self) -> &'static str;
|
||||
fn update(&self) -> Result<(), PackageError>;
|
||||
fn install(&self, list: PackageList) -> Result<(), PackageError>;
|
||||
fn remove(&self, list: PackageList) -> Result<(), PackageError>;
|
||||
}
|
||||
131
src/modules/package/mod.rs
Normal file
131
src/modules/package/mod.rs
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
use serde::Serialize;
|
||||
|
||||
use crate::{Module, ModuleSetup};
|
||||
use crate::facts::{Facts, os::OsFamily};
|
||||
use crate::utils::cmd::CmdOutput;
|
||||
|
||||
use std::boxed::Box;
|
||||
|
||||
pub mod pacman;
|
||||
use pacman::ArchlinuxPackageManager;
|
||||
pub mod apt;
|
||||
use apt::DebianPackageManager;
|
||||
|
||||
pub mod builder;
|
||||
pub use builder::PackageArgsBuilder;
|
||||
|
||||
pub type PackageStatus = ();
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct PackageArgs {
|
||||
name: PackageList,
|
||||
state: PackageState,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum PackageState {
|
||||
Present,
|
||||
Absent,
|
||||
Latest,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PackageModule<Manager> {
|
||||
manager: Manager,
|
||||
args: PackageArgs,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct NoManager;
|
||||
|
||||
impl Module<PackageArgs, (), PackageError> for PackageModule<Box<dyn SpecificPackageManager>> {
|
||||
fn serialize_args(&self) -> serde_json::Value {
|
||||
serde_json::to_value(&self.args).unwrap()
|
||||
}
|
||||
|
||||
fn module_name(&self) -> &'static str {
|
||||
"package"
|
||||
}
|
||||
|
||||
fn run(self) -> Result<(), PackageError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleSetup<PackageArgs, (), PackageError> for PackageModule<NoManager> {
|
||||
fn with_facts(self, facts: &Facts) -> Box<dyn Module<PackageArgs, (), PackageError>> {
|
||||
let Self { args, .. } = self;
|
||||
|
||||
let manager: Box<dyn SpecificPackageManager> = match facts.os.family() {
|
||||
OsFamily::Debian => Box::new(DebianPackageManager),
|
||||
OsFamily::Archlinux => Box::new(ArchlinuxPackageManager),
|
||||
};
|
||||
|
||||
Box::new(PackageModule {
|
||||
args,
|
||||
manager,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl PackageModule<NoManager> {
|
||||
pub fn new() -> PackageArgsBuilder<builder::NoPackage, builder::NoState, builder::NoManager> {
|
||||
PackageArgsBuilder::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub enum PackageError {
|
||||
IoError(String),
|
||||
CmdFail(CmdOutput),
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for PackageError {
|
||||
fn from(e: std::io::Error) -> PackageError {
|
||||
PackageError::IoError(e.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SpecificPackageManager: std::fmt::Debug {
|
||||
fn name(&self) -> &'static str;
|
||||
fn update(&self) -> Result<(), PackageError>;
|
||||
fn install(&self, list: PackageList) -> Result<(), PackageError>;
|
||||
fn remove(&self, list: PackageList) -> Result<(), PackageError>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct PackageList {
|
||||
pub list: Vec<String>,
|
||||
}
|
||||
|
||||
impl PackageList {
|
||||
pub fn list(&self) -> & [ String ] {
|
||||
&self.list
|
||||
}
|
||||
|
||||
pub fn add<T: IntoPackageList>(self, add: T) -> PackageList {
|
||||
let Self { mut list } = self;
|
||||
|
||||
let extend_with = add.into_package_list();
|
||||
list.extend(extend_with.list);
|
||||
|
||||
PackageList {
|
||||
list
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoPackageList {
|
||||
fn into_package_list(self) -> PackageList;
|
||||
}
|
||||
|
||||
impl <T: Into<Vec<String>>> IntoPackageList for T {
|
||||
fn into_package_list(self) -> PackageList {
|
||||
PackageList {
|
||||
list: self.into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
36
src/modules/package/pacman.rs
Normal file
36
src/modules/package/pacman.rs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
use crate::utils::cmd::Cmd;
|
||||
|
||||
use super::{PackageError, PackageList, SpecificPackageManager};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ArchlinuxPackageManager;
|
||||
|
||||
impl SpecificPackageManager for ArchlinuxPackageManager {
|
||||
fn name(&self) -> &'static str {
|
||||
"pacman"
|
||||
}
|
||||
|
||||
fn update(&self) -> Result<(), PackageError> {
|
||||
let res = Cmd::new("pacman").arg("-Sy").run()?;
|
||||
|
||||
if ! res.success {
|
||||
return Err(PackageError::CmdFail(res));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn install(&self, list: PackageList) -> Result<(), PackageError> {
|
||||
let res = Cmd::new("pacman").arg("-S").args(list.list()).run()?;
|
||||
|
||||
if ! res.success {
|
||||
return Err(PackageError::CmdFail(res));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove(&self, _list: PackageList) -> Result<(), PackageError> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue