staxman-old/src/stack/compose.rs

80 lines
2.1 KiB
Rust

use anyhow::Result;
use axum::http::StatusCode;
use futures_util::future::try_join;
use std::path::{Path, PathBuf};
use tempfile::tempdir;
use tokio::fs;
use crate::{
git::ThreadSafeRepository,
http::error::AppError,
node::{error::StackError, nix::parse_arion_compose},
};
use super::{arion, utils, FileList, COMPOSE_FILE, PACKAGE_CONTENTS, PACKAGE_FILE};
pub async fn get(base_dir: &Path, stack_name: &str) -> Result<String> {
let dir = base_dir.join(stack_name);
if !utils::is_stack(&dir).await? {
return Err(StackError::NotFound.into());
}
let contents = tokio::fs::read_to_string(dir.join(COMPOSE_FILE)).await?;
Ok(contents)
}
pub fn commit(
repository: ThreadSafeRepository,
stack_name: &str,
files: &FileList,
message: &str,
) -> Result<()> {
repository.commit_files(
&files
.keys()
.map(|key| PathBuf::from(format!("{}/{}", stack_name, key)))
.collect::<Vec<_>>(),
message,
)?;
Ok(())
}
pub async fn check(arion_bin: &Path, source: &str) -> crate::http::error::Result<String> {
// Check that it's a valid nix tree
let info = parse_arion_compose(source).map_err(|err| AppError::Client {
status: StatusCode::NOT_ACCEPTABLE,
code: "failed-nix-parse",
message: format!("Parse error: {}", err),
})?;
// Create a temporary stack and check that it generates a YAML tree
let dir = tempdir()?;
let path = dir.path();
// Create package file and compose file
try_join(
fs::write(path.join(PACKAGE_FILE), PACKAGE_CONTENTS),
fs::write(path.join(COMPOSE_FILE), source),
)
.await?;
let cmd = arion::run(arion_bin, path, arion::StackCommand::Test).await?;
dir.close()?;
if let arion::CommandStatus::Failure(_, err) = cmd {
Err(AppError::Client {
status: StatusCode::NOT_ACCEPTABLE,
code: "failed-arion-check",
message: format!("Arion {}", err),
})
} else {
Ok(info.project)
}
}
#[inline(always)]
pub fn path(stack_name: &str) -> PathBuf {
format!("{}/{}", stack_name, COMPOSE_FILE).into()
}