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
2.2 KiB

use super::{Add, AddGeneric, AddResult, AddableResource, Runnable, SymbolRunner};
use crate::{ImplementationBuilder, ResourceLocator};
use async_trait::async_trait;
use slog::{debug, o, trace, Logger};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::rc::{Rc, Weak};
#[derive(Debug)]
pub struct Realizer<SR, L, B, S> {
symbol_runner: Rc<SR>,
outer: Weak<S>,
phantom: PhantomData<(L, B)>,
}
impl<SR, L, B, S> Realizer<SR, L, B, S> {
pub fn new(symbol_runner: Rc<SR>, outer: Weak<S>) -> Self {
Self {
symbol_runner,
outer,
phantom: PhantomData::default(),
}
}
}
#[async_trait(?Send)]
impl<R, SR, L, B, S> Add<R> for Realizer<SR, L, B, S>
where
R: AddableResource,
SR: SymbolRunner,
L: ResourceLocator<R>,
B: ImplementationBuilder<R>,
<B as ImplementationBuilder<R>>::Implementation: Runnable + Debug,
S: AddGeneric<B::Prerequisites> + AddGeneric<<L as ResourceLocator<R>>::Prerequisites>,
{
async fn add(&self, logger: &Rc<Logger>, resource: Rc<R>, force_run: bool) -> AddResult<R> {
let setup = self.outer.upgrade().unwrap();
let logger = Rc::new(logger.new(o!("resource" => format!("{resource:?}"))));
trace!(logger, "(force_run is {})", force_run);
let (location, location_prereqs) = L::locate(&resource);
trace!(logger, "Adding location prereqs ...");
let (_, location_prereqs_did_run) = (*setup)
.add_generic(&logger, location_prereqs, false)
.await?;
trace!(
logger,
"Location prereqs did_run: {}",
location_prereqs_did_run
);
trace!(logger, "Adding implementation prereqs ...");
let (prereqs, prereqs_did_run) = (*setup)
.add_generic(&logger, B::prerequisites(&resource), false)
.await?;
trace!(
logger,
"Implementation prereqs did_run: {}",
prereqs_did_run
);
trace!(logger, "Running implementation ...");
let implementation = B::create(&resource, &location, prereqs);
let did_run = implementation
.run(
&*self.symbol_runner,
&logger,
force_run || location_prereqs_did_run || prereqs_did_run,
)
.await?;
debug!(logger, "done.");
Ok((location, did_run))
}
}