This commit is contained in:
2026-03-02 05:05:33 +01:00
parent 08c1d0c605
commit a066bfb17a
31 changed files with 1239 additions and 0 deletions

119
crete/src/node.rs Normal file
View File

@@ -0,0 +1,119 @@
use std::net::Ipv4Addr;
use optional_struct::{Applicable, optional_struct};
use schemars::JsonSchema;
use serde::Deserialize;
use crate::{
base_dir,
cluster::Cluster,
patch::{OptionalPatches, Patches},
};
#[derive(Debug, Deserialize, JsonSchema, Clone, Copy, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
enum NodeType {
Worker,
ControlPlane,
}
#[derive(Debug, Deserialize, JsonSchema, Clone, Copy, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
enum NodeArch {
Amd64,
}
#[optional_struct]
#[derive(Debug, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct Network {
interface: String,
ip: Ipv4Addr,
netmask: Ipv4Addr,
gateway: Ipv4Addr,
dns: [Ipv4Addr; 2],
advertise_routes: bool,
}
#[optional_struct]
#[derive(Debug, Deserialize, JsonSchema, Default)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
struct Install {
auto: bool,
disk: String,
serial: Option<String>,
}
#[optional_struct]
#[derive(Debug, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct Node {
#[serde(skip_deserializing)]
hostname: String,
arch: NodeArch,
r#type: NodeType,
#[optional_rename(OptionalNetwork)]
network: Network,
// TODO: Type that verifies url?
ntp: String,
#[optional_rename(OptionalInstall)]
#[serde(default)]
install: Install,
kernel_args: Vec<String>,
#[optional_rename(OptionalPatches)]
#[serde(default)]
patches: Patches,
// TODO: Per machine patches, append to global list of patches
// Any patches are specified under default they will get overridden
}
impl Node {
pub fn get(mut cluster: Cluster, node_name: &str) -> Self {
let mut path = base_dir().join("nodes").join(node_name);
let named = OptionalNode {
hostname: Some(
path.file_name()
.expect("Path should be valid")
.to_string_lossy()
.to_string(),
),
..OptionalNode::default()
};
path.add_extension("yaml");
let content = std::fs::read_to_string(path).unwrap();
let node: OptionalNode = serde_yaml::from_str(&content).unwrap();
// We want all vectors to be empty vectors by default
// Sadly we have to this manually
// TODO: Find a better way of doing this
let default = OptionalNode {
patches: OptionalPatches {
all: vec![].into(),
control_plane: vec![].into(),
},
kernel_args: vec![].into(),
..Default::default()
};
// Combine all the optional node parts into complete struct
let mut node: Node = default
// Apply cluster default settings
.apply(cluster.default)
// Apply hostname based on filename
.apply(named)
// Override node specific settings
.apply(node)
.try_into()
.unwrap();
// Prepend the cluster base values
cluster.base.kernel_args.extend(node.kernel_args);
node.kernel_args = cluster.base.kernel_args;
cluster.base.patches.extend(node.patches);
node.patches = cluster.base.patches;
node
}
}