120 lines
3.3 KiB
Rust
120 lines
3.3 KiB
Rust
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
|
|
}
|
|
}
|