feat: can recursively load files
Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
parent
06ad4515c2
commit
461f8acb73
@ -1,3 +1,5 @@
|
|||||||
|
#![feature(map_try_insert)]
|
||||||
|
|
||||||
pub mod components;
|
pub mod components;
|
||||||
pub use components::*;
|
pub use components::*;
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
|
use futures::{future::BoxFuture, FutureExt};
|
||||||
use minijinja::context;
|
use minijinja::context;
|
||||||
use tokio::io::AsyncWriteExt;
|
use tokio::io::AsyncWriteExt;
|
||||||
use tokio_stream::{wrappers::ReadDirStream, StreamExt};
|
use tokio_stream::{wrappers::ReadDirStream, StreamExt};
|
||||||
@ -32,6 +33,9 @@ impl Default for ProcessOpts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TEMPLATES_PATH_PREFIX: &str = "templates/clusters";
|
||||||
|
const CUDDLE_PLAN_PATH_PREFIX: &str = ".cuddle/plan";
|
||||||
|
|
||||||
pub async fn process_opts(
|
pub async fn process_opts(
|
||||||
components: impl IntoIterator<Item = impl IntoComponent>,
|
components: impl IntoIterator<Item = impl IntoComponent>,
|
||||||
opts: ProcessOpts,
|
opts: ProcessOpts,
|
||||||
@ -44,18 +48,17 @@ pub async fn process_opts(
|
|||||||
let path = opts.path.canonicalize().context("failed to find folder")?;
|
let path = opts.path.canonicalize().context("failed to find folder")?;
|
||||||
|
|
||||||
let cuddle_path = path.join("cuddle.yaml");
|
let cuddle_path = path.join("cuddle.yaml");
|
||||||
let template = path.join("templates").join("clusters");
|
|
||||||
|
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"searching for templates in: {} with cuddle: {}",
|
"searching for templates in: {} with cuddle: {}",
|
||||||
template.display(),
|
path.display(),
|
||||||
cuddle_path.display()
|
cuddle_path.display()
|
||||||
);
|
);
|
||||||
|
|
||||||
let clusters = read_cuddle_section(&cuddle_path).await?;
|
let clusters = read_cuddle_section(&cuddle_path).await?;
|
||||||
tracing::debug!("found clusters: {:?}", clusters);
|
tracing::debug!("found clusters: {:?}", clusters);
|
||||||
|
|
||||||
let template_files = load_template_files(&template).await?;
|
let template_files = load_template_files(&path).await?;
|
||||||
tracing::debug!("found files: {:?}", template_files);
|
tracing::debug!("found files: {:?}", template_files);
|
||||||
|
|
||||||
tokio::fs::remove_dir_all(&opts.output).await?;
|
tokio::fs::remove_dir_all(&opts.output).await?;
|
||||||
@ -100,31 +103,70 @@ async fn read_cuddle_section(path: &Path) -> anyhow::Result<CuddleClusters> {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct TemplateFiles {
|
struct TemplateFiles {
|
||||||
templates: Vec<PathBuf>,
|
templates: HashMap<String, PathBuf>,
|
||||||
raw: Vec<PathBuf>,
|
raw: HashMap<String, PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_template_files(path: &Path) -> anyhow::Result<TemplateFiles> {
|
impl TemplateFiles {
|
||||||
Ok(TemplateFiles {
|
fn merge(&mut self, template_files: TemplateFiles) {
|
||||||
templates: read_dir(path)
|
for (name, path) in template_files.templates {
|
||||||
|
// Ignored if the key is already present
|
||||||
|
let _ = self.templates.try_insert(name, path);
|
||||||
|
}
|
||||||
|
for (name, path) in template_files.raw {
|
||||||
|
// Ignored if the key is already present
|
||||||
|
let _ = self.raw.try_insert(name, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_template_files(path: &Path) -> BoxFuture<'static, anyhow::Result<TemplateFiles>> {
|
||||||
|
let template_path = path.join(TEMPLATES_PATH_PREFIX);
|
||||||
|
let path = path.to_path_buf();
|
||||||
|
|
||||||
|
tracing::info!("reading folder: {}", path.display());
|
||||||
|
|
||||||
|
async move {
|
||||||
|
let templates = read_dir(&template_path)
|
||||||
.await?
|
.await?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|i| i.extension().and_then(|e| e.to_str()) == Some("jinja2"))
|
.filter(|(_, i)| i.extension().and_then(|e| e.to_str()) == Some("jinja2"))
|
||||||
.collect(),
|
.collect();
|
||||||
raw: read_dir(&path.join("raw")).await.unwrap_or_default(),
|
let raw = read_dir(&template_path.join("raw"))
|
||||||
})
|
.await
|
||||||
|
.unwrap_or_default();
|
||||||
|
let mut template_files = TemplateFiles { templates, raw };
|
||||||
|
|
||||||
|
let nested_path = path.join(CUDDLE_PLAN_PATH_PREFIX);
|
||||||
|
tracing::info!("trying to read: {}", nested_path.display());
|
||||||
|
if nested_path.exists() {
|
||||||
|
let nested = load_template_files(&nested_path).await?;
|
||||||
|
template_files.merge(nested);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(template_files)
|
||||||
|
}
|
||||||
|
.boxed()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read_dir(path: &Path) -> anyhow::Result<Vec<PathBuf>> {
|
async fn read_dir(path: &Path) -> anyhow::Result<HashMap<String, PathBuf>> {
|
||||||
let template_dir = tokio::fs::read_dir(path).await?;
|
let template_dir = tokio::fs::read_dir(path).await?;
|
||||||
let mut template_dir_stream = ReadDirStream::new(template_dir);
|
let mut template_dir_stream = ReadDirStream::new(template_dir);
|
||||||
|
|
||||||
let mut paths = Vec::new();
|
let mut paths = HashMap::new();
|
||||||
while let Some(entry) = template_dir_stream.next().await {
|
while let Some(entry) = template_dir_stream.next().await {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
|
|
||||||
if entry.metadata().await?.is_file() {
|
if entry.metadata().await?.is_file() {
|
||||||
paths.push(entry.path());
|
paths.insert(
|
||||||
|
entry
|
||||||
|
.path()
|
||||||
|
.file_name()
|
||||||
|
.expect("the file to have a filename")
|
||||||
|
.to_string_lossy()
|
||||||
|
.to_string(),
|
||||||
|
entry.path(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +181,7 @@ async fn process_templates(
|
|||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
for (environment, value) in clusters.iter() {
|
for (environment, value) in clusters.iter() {
|
||||||
process_cluster(
|
process_cluster(
|
||||||
&components,
|
components,
|
||||||
value,
|
value,
|
||||||
environment,
|
environment,
|
||||||
template_files,
|
template_files,
|
||||||
@ -158,11 +200,11 @@ async fn process_cluster(
|
|||||||
template_files: &TemplateFiles,
|
template_files: &TemplateFiles,
|
||||||
dest: &Path,
|
dest: &Path,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
for template_file in &template_files.templates {
|
for (_, template_file) in &template_files.templates {
|
||||||
process_template_file(components, value, environment, template_file, dest).await?;
|
process_template_file(components, value, environment, template_file, dest).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for raw_file in &template_files.raw {
|
for (_, raw_file) in &template_files.raw {
|
||||||
process_raw_file(environment, raw_file, dest).await?;
|
process_raw_file(environment, raw_file, dest).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
crates/cuddle-clusters/tests/nested/cuddle.yaml
Normal file
2
crates/cuddle-clusters/tests/nested/cuddle.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
cuddle/clusters:
|
||||||
|
dev:
|
@ -0,0 +1 @@
|
|||||||
|
nested
|
@ -0,0 +1 @@
|
|||||||
|
nested
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -0,0 +1 @@
|
|||||||
|
service
|
@ -27,6 +27,13 @@ async fn both() -> anyhow::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn nested() -> anyhow::Result<()> {
|
||||||
|
run_test("nested").await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn jinja() -> anyhow::Result<()> {
|
async fn jinja() -> anyhow::Result<()> {
|
||||||
run_test("jinja").await?;
|
run_test("jinja").await?;
|
||||||
|
Loading…
Reference in New Issue
Block a user