refactor: Move modules into their own directory structure (#80)
This separates out the module template logic so that it is easier to undertstand what each section does. This will also allow creating in repo documentation for any special modules that don't use a bash base.
This commit is contained in:
parent
0b4e1003a2
commit
4c8a8f7aa8
22 changed files with 239 additions and 688 deletions
7
src/akmods_info.rs
Normal file
7
src/akmods_info.rs
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
use typed_builder::TypedBuilder;
|
||||
|
||||
#[derive(Debug, Clone, TypedBuilder, PartialEq, Eq, Hash)]
|
||||
pub struct AkmodsInfo {
|
||||
pub images: (String, Option<String>),
|
||||
pub stage_name: String,
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
use std::{
|
||||
collections::HashSet,
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
process,
|
||||
|
|
@ -12,15 +11,12 @@ use log::{debug, error, info, trace};
|
|||
use typed_builder::TypedBuilder;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
constants::*,
|
||||
module_recipe::{Module, ModuleExt, Recipe},
|
||||
};
|
||||
use crate::{constants::*, module_recipe::Recipe};
|
||||
|
||||
use super::BlueBuildCommand;
|
||||
|
||||
#[derive(Debug, Clone, Template, TypedBuilder)]
|
||||
#[template(path = "Containerfile")]
|
||||
#[template(path = "Containerfile.j2", escape = "none")]
|
||||
pub struct ContainerFileTemplate<'a> {
|
||||
recipe: &'a Recipe<'a>,
|
||||
|
||||
|
|
@ -38,6 +34,24 @@ pub struct ContainerFileTemplate<'a> {
|
|||
#[template(path = "export.sh", escape = "none")]
|
||||
pub struct ExportsTemplate;
|
||||
|
||||
impl ExportsTemplate {
|
||||
fn print_script(&self) -> String {
|
||||
trace!("print_script({self})");
|
||||
|
||||
format!(
|
||||
"\"{}\"",
|
||||
self.render()
|
||||
.unwrap_or_else(|e| {
|
||||
error!("Failed to render export.sh script: {e}");
|
||||
process::exit(1);
|
||||
})
|
||||
.replace('\n', "\\n")
|
||||
.replace('\"', "\\\"")
|
||||
.replace('$', "\\$")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Args, TypedBuilder)]
|
||||
pub struct TemplateCommand {
|
||||
/// The recipe file to create a template from
|
||||
|
|
@ -114,23 +128,6 @@ impl TemplateCommand {
|
|||
// ========================= Helpers ====================== //
|
||||
// ======================================================== //
|
||||
|
||||
fn print_script(script_contents: &ExportsTemplate) -> String {
|
||||
trace!("print_script({script_contents})");
|
||||
|
||||
format!(
|
||||
"\"{}\"",
|
||||
script_contents
|
||||
.render()
|
||||
.unwrap_or_else(|e| {
|
||||
error!("Failed to render export.sh script: {e}");
|
||||
process::exit(1);
|
||||
})
|
||||
.replace('\n', "\\n")
|
||||
.replace('\"', "\\\"")
|
||||
.replace('$', "\\$")
|
||||
)
|
||||
}
|
||||
|
||||
fn has_cosign_file() -> bool {
|
||||
trace!("has_cosign_file()");
|
||||
std::env::current_dir()
|
||||
|
|
@ -138,33 +135,6 @@ fn has_cosign_file() -> bool {
|
|||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_module_type_list(module: &Module, typ: &str, list_key: &str) -> Option<Vec<String>> {
|
||||
if module.module_type.as_ref()? == typ {
|
||||
Some(
|
||||
module
|
||||
.config
|
||||
.get(list_key)?
|
||||
.as_sequence()?
|
||||
.iter()
|
||||
.filter_map(|t| Some(t.as_str()?.to_owned()))
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_containerfile_list(module: &Module) -> Option<Vec<String>> {
|
||||
get_module_type_list(module, "containerfile", "containerfiles")
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn get_containerfile_snippets(module: &Module) -> Option<Vec<String>> {
|
||||
get_module_type_list(module, "containerfile", "snippets")
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn print_containerfile(containerfile: &str) -> String {
|
||||
trace!("print_containerfile({containerfile})");
|
||||
|
|
@ -182,32 +152,6 @@ fn print_containerfile(containerfile: &str) -> String {
|
|||
file
|
||||
}
|
||||
|
||||
fn print_module_context(module: &Module) -> String {
|
||||
serde_json::to_string(module).unwrap_or_else(|e| {
|
||||
error!("Failed to parse module!!!!!: {e}");
|
||||
process::exit(1);
|
||||
})
|
||||
}
|
||||
|
||||
fn get_files_list(module: &Module) -> Option<Vec<(String, String)>> {
|
||||
Some(
|
||||
module
|
||||
.config
|
||||
.get("files")?
|
||||
.as_sequence()?
|
||||
.iter()
|
||||
.filter_map(|entry| entry.as_mapping())
|
||||
.flatten()
|
||||
.filter_map(|(src, dest)| {
|
||||
Some((
|
||||
format!("./config/files/{}", src.as_str()?),
|
||||
dest.as_str()?.to_string(),
|
||||
))
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_github_repo_owner() -> Option<String> {
|
||||
Some(env::var(GITHUB_REPOSITORY_OWNER).ok()?.to_lowercase())
|
||||
}
|
||||
|
|
@ -228,56 +172,3 @@ fn modules_exists() -> bool {
|
|||
let mod_path = Path::new("modules");
|
||||
mod_path.exists() && mod_path.is_dir()
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, TypedBuilder, PartialEq, Eq, Hash)]
|
||||
struct AkmodsInfo {
|
||||
images: (String, Option<String>),
|
||||
stage_name: String,
|
||||
}
|
||||
|
||||
fn get_akmods_info_list(module_ext: &ModuleExt, os_version: &str) -> Vec<AkmodsInfo> {
|
||||
trace!("get_akmods_image_list({module_ext:#?}, {os_version})");
|
||||
|
||||
let mut seen = HashSet::new();
|
||||
|
||||
module_ext
|
||||
.modules
|
||||
.iter()
|
||||
.filter(|module| module.module_type.as_ref().is_some_and(|t| t == "akmods"))
|
||||
.map(|module| generate_akmods_info(module, os_version))
|
||||
.filter(|image| seen.insert(image.clone()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn generate_akmods_info(module: &Module, os_version: &str) -> AkmodsInfo {
|
||||
trace!("generate_akmods_base({module:#?}, {os_version})");
|
||||
|
||||
let base = module
|
||||
.config
|
||||
.get("base")
|
||||
.map(|b| b.as_str().unwrap_or_default());
|
||||
let nvidia_version = module
|
||||
.config
|
||||
.get("nvidia-version")
|
||||
.map(|v| v.as_u64().unwrap_or_default());
|
||||
|
||||
AkmodsInfo::builder()
|
||||
.images(match (base, nvidia_version) {
|
||||
(Some(b), Some(nv)) if !b.is_empty() && nv > 0 => (
|
||||
format!("akmods:{b}-{os_version}"),
|
||||
Some(format!("akmods-nvidia:{b}-{os_version}-{nv}")),
|
||||
),
|
||||
(Some(b), _) if !b.is_empty() => (format!("akmods:{b}-{os_version}"), None),
|
||||
(_, Some(nv)) if nv > 0 => (
|
||||
format!("akmods:main-{os_version}"),
|
||||
Some(format!("akmods-nvidia:main-{os_version}")),
|
||||
),
|
||||
_ => (format!("akmods:main-{os_version}"), None),
|
||||
})
|
||||
.stage_name(format!(
|
||||
"{}{}",
|
||||
base.unwrap_or("main"),
|
||||
nvidia_version.map_or_else(String::default, |nv| format!("-{nv}"))
|
||||
))
|
||||
.build()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
shadow_rs::shadow!(shadow);
|
||||
|
||||
pub mod akmods_info;
|
||||
pub mod commands;
|
||||
pub mod constants;
|
||||
pub mod module_recipe;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
use std::{
|
||||
borrow::Cow,
|
||||
collections::HashMap,
|
||||
collections::{HashMap, HashSet},
|
||||
env, fs,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
process::{self, Command},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
|
|
@ -17,6 +17,7 @@ use serde_yaml::Value;
|
|||
use typed_builder::TypedBuilder;
|
||||
|
||||
use crate::{
|
||||
akmods_info::AkmodsInfo,
|
||||
constants::*,
|
||||
ops::{self, check_command_exists},
|
||||
};
|
||||
|
|
@ -236,6 +237,19 @@ impl ModuleExt<'_> {
|
|||
Ok,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_akmods_info_list(&self, os_version: &str) -> Vec<AkmodsInfo> {
|
||||
trace!("get_akmods_image_list({self:#?}, {os_version})");
|
||||
|
||||
let mut seen = HashSet::new();
|
||||
|
||||
self.modules
|
||||
.iter()
|
||||
.filter(|module| module.module_type.as_ref().is_some_and(|t| t == "akmods"))
|
||||
.map(|module| module.generate_akmods_info(os_version))
|
||||
.filter(|image| seen.insert(image.clone()))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, TypedBuilder)]
|
||||
|
|
@ -257,7 +271,7 @@ pub struct Module<'a> {
|
|||
pub config: IndexMap<String, Value>,
|
||||
}
|
||||
|
||||
impl Module<'_> {
|
||||
impl<'a> Module<'a> {
|
||||
#[must_use]
|
||||
pub fn get_modules(modules: &[Self]) -> Vec<Self> {
|
||||
modules
|
||||
|
|
@ -276,6 +290,90 @@ impl Module<'_> {
|
|||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_module_type_list(&'a self, typ: &str, list_key: &str) -> Option<Vec<String>> {
|
||||
if self.module_type.as_ref()? == typ {
|
||||
Some(
|
||||
self.config
|
||||
.get(list_key)?
|
||||
.as_sequence()?
|
||||
.iter()
|
||||
.filter_map(|t| Some(t.as_str()?.to_owned()))
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_containerfile_list(&'a self) -> Option<Vec<String>> {
|
||||
self.get_module_type_list("containerfile", "containerfiles")
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_containerfile_snippets(&'a self) -> Option<Vec<String>> {
|
||||
self.get_module_type_list("containerfile", "snippets")
|
||||
}
|
||||
|
||||
pub fn print_module_context(&'a self) -> String {
|
||||
serde_json::to_string(self).unwrap_or_else(|e| {
|
||||
error!("Failed to parse module!!!!!: {e}");
|
||||
process::exit(1);
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_files_list(&'a self) -> Option<Vec<(String, String)>> {
|
||||
Some(
|
||||
self.config
|
||||
.get("files")?
|
||||
.as_sequence()?
|
||||
.iter()
|
||||
.filter_map(|entry| entry.as_mapping())
|
||||
.flatten()
|
||||
.filter_map(|(src, dest)| {
|
||||
Some((
|
||||
format!("./config/files/{}", src.as_str()?),
|
||||
dest.as_str()?.to_string(),
|
||||
))
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn generate_akmods_info(&'a self, os_version: &str) -> AkmodsInfo {
|
||||
trace!("generate_akmods_base({self:#?}, {os_version})");
|
||||
|
||||
let base = self
|
||||
.config
|
||||
.get("base")
|
||||
.map(|b| b.as_str().unwrap_or_default());
|
||||
let nvidia_version = self
|
||||
.config
|
||||
.get("nvidia-version")
|
||||
.map(|v| v.as_u64().unwrap_or_default());
|
||||
|
||||
AkmodsInfo::builder()
|
||||
.images(match (base, nvidia_version) {
|
||||
(Some(b), Some(nv)) if !b.is_empty() && nv > 0 => (
|
||||
format!("akmods:{b}-{os_version}"),
|
||||
Some(format!("akmods-nvidia:{b}-{os_version}-{nv}")),
|
||||
),
|
||||
(Some(b), _) if !b.is_empty() => (format!("akmods:{b}-{os_version}"), None),
|
||||
(_, Some(nv)) if nv > 0 => (
|
||||
format!("akmods:main-{os_version}"),
|
||||
Some(format!("akmods-nvidia:main-{os_version}")),
|
||||
),
|
||||
_ => (format!("akmods:main-{os_version}"), None),
|
||||
})
|
||||
.stage_name(format!(
|
||||
"{}{}",
|
||||
base.unwrap_or("main"),
|
||||
nvidia_version.map_or_else(String::default, |nv| format!("-{nv}"))
|
||||
))
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue