pub(crate) mod trait_impl;
use crate::HostInventoryVarsGenerator;
use anyhow::Result;
use cdk_ansible_core::core::{
InventoryChild, InventoryRoot, OptU, Play, PlayOptions, StringOrVecString, Task,
};
use futures::future::BoxFuture;
use std::fmt;
use std::sync::Arc;
#[derive(Clone)]
pub struct PlayL2 {
pub name: String,
pub hosts: HostsL2,
pub options: PlayOptions,
pub tasks: Vec<Task>,
}
impl PlayL2 {
pub fn try_play(self) -> Result<Play> {
Ok(Play {
name: self.name,
hosts: self.hosts.try_hosts()?,
options: self.options,
tasks: self.tasks,
})
}
}
impl From<PlayL2> for ExePlayL2 {
fn from(play_l2: PlayL2) -> Self {
ExePlayL2::Single(Box::new(play_l2))
}
}
#[derive(Debug, Clone)]
pub enum ExePlayL2 {
Sequential(Vec<ExePlayL2>),
Parallel(Vec<ExePlayL2>),
Single(Box<PlayL2>),
}
pub trait LazyPlayL2 {
fn lazy_play_l2(&self) -> BoxFuture<'static, Result<ExePlayL2>>;
}
#[derive(Clone)]
pub struct HostsL2(Vec<Arc<dyn HostInventoryVarsGenerator + Send + Sync>>);
impl HostsL2 {
pub fn new(hosts: Vec<Arc<dyn HostInventoryVarsGenerator + Send + Sync>>) -> Self {
Self(hosts)
}
pub fn try_hosts(&self) -> Result<StringOrVecString> {
Ok(self
.0
.iter()
.map(|h| h.gen_host_vars())
.collect::<Result<Vec<_>>>()?
.into_iter()
.map(|h| h.ansible_host.to_string())
.collect::<Vec<_>>()
.into())
}
pub fn to_inventory_root(&self) -> Result<InventoryRoot> {
Ok(InventoryRoot {
all: InventoryChild {
hosts: OptU::Some(
self.0
.iter()
.map(|h| h.gen_host_vars())
.collect::<Result<Vec<_>>>()?
.into_iter()
.collect(),
),
..Default::default()
},
})
}
}
impl fmt::Debug for PlayL2 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PlayL2")
.field("name", &self.name)
.field("hosts", &"hosts (TODO)")
.field("options", &self.options)
.field("tasks", &self.tasks)
.finish()
}
}
#[derive(Clone)]
pub enum LazyExePlayL2 {
Sequential(Vec<LazyExePlayL2>),
Parallel(Vec<LazyExePlayL2>),
Single(Arc<dyn LazyPlayL2 + Send + Sync>),
}
pub use LazyExePlayL2 as LEP;
pub use LazyExePlayL2::Parallel as LEPParallelL2;
pub use LazyExePlayL2::Sequential as LEPSequentialL2;
pub use LazyExePlayL2::Single as LEPSingleL2;
#[cfg(test)]
mod test_exe_play_struct {
use super::*;
use crate::utils::test::*;
#[test]
fn test_sequential_play_exec() {
let _play_exec = LEPSequentialL2(vec![
LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new("sample1"))),
LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new("sample2"))),
LEPParallelL2(vec![
LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new("sample3"))),
LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new("sample4"))),
]),
]);
}
}
impl LazyExePlayL2 {
pub fn push(&mut self, p: LazyExePlayL2) {
match self {
LazyExePlayL2::Sequential(plays) => plays.push(p),
LazyExePlayL2::Parallel(plays) => plays.push(p),
LazyExePlayL2::Single(_) => {
let p1 = self.clone();
*self = LEPSequentialL2(vec![p1, p]);
}
}
}
pub fn push_play(&mut self, p: Arc<dyn LazyPlayL2 + Send + Sync>) {
match self {
LazyExePlayL2::Sequential(plays) => plays.push(p.into()),
LazyExePlayL2::Parallel(plays) => plays.push(p.into()),
LazyExePlayL2::Single(_) => {
let p1 = self.clone();
*self = LEPSequentialL2(vec![p1, p.into()]);
}
}
}
}
impl From<Arc<dyn LazyPlayL2 + Send + Sync>> for LazyExePlayL2 {
fn from(p: Arc<dyn LazyPlayL2 + Send + Sync>) -> Self {
LazyExePlayL2::Single(p)
}
}
#[cfg(test)]
mod test_exe_play_l2_push {
use super::*;
use crate::utils::test::*;
#[test]
fn test_exe_play_single_push() {
let mut exe_play = LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new("sample1")));
exe_play.push(LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new(
"sample2",
))));
match exe_play {
LazyExePlayL2::Sequential(plays) => {
assert_eq!(plays.len(), 2);
}
_ => unreachable!("exe_play should be LEPSequentialL2"),
}
}
#[test]
fn test_exe_play_sequential_push() {
let mut exe_play = LEPSequentialL2(vec![LEPSingleL2(Arc::new(
SampleLazyPlayL2Helper::new("sample1"),
))]);
exe_play.push(LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new(
"sample2",
))));
match exe_play {
LazyExePlayL2::Sequential(plays) => {
assert_eq!(plays.len(), 2);
}
_ => unreachable!("exe_play should be LEPSequentialL2"),
}
}
#[test]
fn test_exe_play_parallel_push() {
let mut exe_play = LEPParallelL2(vec![LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new(
"sample1",
)))]);
exe_play.push(LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new(
"sample2",
))));
match exe_play {
LazyExePlayL2::Parallel(plays) => {
assert_eq!(plays.len(), 2);
}
_ => unreachable!("exe_play should be LEPParallelL2"),
}
}
}
#[cfg(test)]
mod test_exe_play_l2_push_play {
use super::*;
use crate::utils::test::*;
#[test]
fn test_exe_play_single_push_play() {
let mut exe_play = LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new("sample1")));
exe_play.push_play(Arc::new(SampleLazyPlayL2Helper::new("sample2")));
match exe_play {
LazyExePlayL2::Sequential(plays) => {
assert_eq!(plays.len(), 2);
}
_ => unreachable!("exe_play should be LEPSequentialL2"),
}
}
#[test]
fn test_exe_play_sequential_push_play() {
let mut exe_play = LEPSequentialL2(vec![LEPSingleL2(Arc::new(
SampleLazyPlayL2Helper::new("sample1"),
))]);
exe_play.push_play(Arc::new(SampleLazyPlayL2Helper::new("sample2")));
match exe_play {
LazyExePlayL2::Sequential(plays) => {
assert_eq!(plays.len(), 2);
}
_ => unreachable!("exe_play should be LEPSequentialL2"),
}
}
#[test]
fn test_exe_play_parallel_push_play() {
let mut exe_play = LEPParallelL2(vec![LEPSingleL2(Arc::new(SampleLazyPlayL2Helper::new(
"sample1",
)))]);
exe_play.push_play(Arc::new(SampleLazyPlayL2Helper::new("sample2")));
match exe_play {
LazyExePlayL2::Parallel(plays) => {
assert_eq!(plays.len(), 2);
}
_ => unreachable!("exe_play should be LEPParallelL2"),
}
}
}