mirror of
https://github.com/logos-blockchain/logos-blockchain-testing.git
synced 2026-01-12 02:03:10 +00:00
107 lines
3.1 KiB
Rust
107 lines
3.1 KiB
Rust
use std::{
|
|
env, fs,
|
|
path::{Path, PathBuf},
|
|
};
|
|
|
|
use anyhow::Context as _;
|
|
use tera::Context as TeraContext;
|
|
|
|
use crate::descriptor::ComposeDescriptor;
|
|
|
|
const TEMPLATE_RELATIVE_PATH: &str =
|
|
"testing-framework/runners/compose/assets/docker-compose.yml.tera";
|
|
|
|
/// Errors when templating docker-compose files.
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum TemplateError {
|
|
#[error("failed to resolve repository root for compose template: {source}")]
|
|
RepositoryRoot {
|
|
#[source]
|
|
source: anyhow::Error,
|
|
},
|
|
#[error("failed to read compose template at {path}: {source}")]
|
|
Read {
|
|
path: PathBuf,
|
|
#[source]
|
|
source: std::io::Error,
|
|
},
|
|
#[error("failed to serialise compose descriptor for templating: {source}")]
|
|
Serialize {
|
|
#[source]
|
|
source: tera::Error,
|
|
},
|
|
#[error("failed to render compose template at {path}: {source}")]
|
|
Render {
|
|
path: PathBuf,
|
|
#[source]
|
|
source: tera::Error,
|
|
},
|
|
#[error("failed to write compose file at {path}: {source}")]
|
|
Write {
|
|
path: PathBuf,
|
|
#[source]
|
|
source: std::io::Error,
|
|
},
|
|
}
|
|
|
|
/// Render and write the compose file to disk.
|
|
pub fn write_compose_file(
|
|
descriptor: &ComposeDescriptor,
|
|
compose_path: &Path,
|
|
) -> Result<(), TemplateError> {
|
|
TemplateSource::load()?.write(descriptor, compose_path)
|
|
}
|
|
|
|
struct TemplateSource {
|
|
path: PathBuf,
|
|
contents: String,
|
|
}
|
|
|
|
impl TemplateSource {
|
|
fn load() -> Result<Self, TemplateError> {
|
|
let repo_root =
|
|
repository_root().map_err(|source| TemplateError::RepositoryRoot { source })?;
|
|
let path = repo_root.join(TEMPLATE_RELATIVE_PATH);
|
|
let contents = fs::read_to_string(&path).map_err(|source| TemplateError::Read {
|
|
path: path.clone(),
|
|
source,
|
|
})?;
|
|
|
|
Ok(Self { path, contents })
|
|
}
|
|
|
|
fn render(&self, descriptor: &ComposeDescriptor) -> Result<String, TemplateError> {
|
|
let context = TeraContext::from_serialize(descriptor)
|
|
.map_err(|source| TemplateError::Serialize { source })?;
|
|
|
|
tera::Tera::one_off(&self.contents, &context, false).map_err(|source| {
|
|
TemplateError::Render {
|
|
path: self.path.clone(),
|
|
source,
|
|
}
|
|
})
|
|
}
|
|
|
|
fn write(&self, descriptor: &ComposeDescriptor, output: &Path) -> Result<(), TemplateError> {
|
|
let rendered = self.render(descriptor)?;
|
|
fs::write(output, rendered).map_err(|source| TemplateError::Write {
|
|
path: output.to_path_buf(),
|
|
source,
|
|
})
|
|
}
|
|
}
|
|
|
|
/// Resolve the repository root, respecting `CARGO_WORKSPACE_DIR` override.
|
|
pub fn repository_root() -> anyhow::Result<PathBuf> {
|
|
env::var("CARGO_WORKSPACE_DIR")
|
|
.map(PathBuf::from)
|
|
.or_else(|_| {
|
|
Path::new(env!("CARGO_MANIFEST_DIR"))
|
|
.parent()
|
|
.and_then(Path::parent)
|
|
.and_then(Path::parent)
|
|
.map(PathBuf::from)
|
|
.context("resolving repository root from manifest dir")
|
|
})
|
|
}
|