WIP
This commit is contained in:
1
crete/.gitignore
vendored
Normal file
1
crete/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
target/
|
||||
223
crete/Cargo.lock
generated
Normal file
223
crete/Cargo.lock
generated
Normal file
@@ -0,0 +1,223 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "crete"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"optional_struct",
|
||||
"regress",
|
||||
"repo_path_lib",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
||||
|
||||
[[package]]
|
||||
name = "optional_struct"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14199f59efce6ed2c5854f0abc725c32eedfbd02c6ef82c9733c726f3fc6dc91"
|
||||
dependencies = [
|
||||
"optional_struct_macro",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "optional_struct_macro"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5eba042d9efe5e108e0df9ce2f85c540fc4f94f41c6821cbcf70ed47c1221da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regress"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2057b2325e68a893284d1538021ab90279adac1139957ca2a74426c6f118fb48"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "repo_path_lib"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d4f67a73ddc563e6fb8bac035c9c76de29af2e4ad6031dc49bb5a2cd0742fca"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||
13
crete/Cargo.toml
Normal file
13
crete/Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "crete"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
optional_struct = "0.5.2"
|
||||
regress = "0.10.5"
|
||||
repo_path_lib = "1.2.4"
|
||||
semver = { version = "1.0.27", features = ["serde"] }
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.149"
|
||||
serde_yaml = "0.9.34"
|
||||
61
crete/src/cluster.rs
Normal file
61
crete/src/cluster.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
base_dir,
|
||||
node::{Node, OptionalNode},
|
||||
patch::Patches,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct Base {
|
||||
#[serde(default)]
|
||||
pub(crate) kernel_args: Vec<String>,
|
||||
#[serde(default)]
|
||||
pub(crate) patches: Patches,
|
||||
}
|
||||
|
||||
// TODO: Extra version validation? Make sure it exists?
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct Version {
|
||||
kubernetes: semver::Version,
|
||||
talos: semver::Version,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct Cluster {
|
||||
#[serde(skip_deserializing)]
|
||||
name: String,
|
||||
version: Version,
|
||||
nodes: Vec<String>,
|
||||
production: bool,
|
||||
control_plane_ip: Ipv4Addr,
|
||||
#[serde(default)]
|
||||
pub(crate) default: OptionalNode,
|
||||
pub(crate) base: Base,
|
||||
// pub secrets_file: PathBuf,
|
||||
}
|
||||
|
||||
impl Cluster {
|
||||
pub fn get(cluster_name: &str) -> Self {
|
||||
let mut path = base_dir().join("clusters").join(cluster_name);
|
||||
path.add_extension("yaml");
|
||||
let content = std::fs::read_to_string(path).unwrap();
|
||||
|
||||
let mut cluster: Self = serde_yaml::from_str(&content).unwrap();
|
||||
cluster.name = cluster_name.to_string();
|
||||
|
||||
cluster
|
||||
}
|
||||
|
||||
pub fn nodes(&self) -> Vec<Node> {
|
||||
self.nodes
|
||||
.iter()
|
||||
.map(|node_name| Node::get(self.clone(), node_name))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
11
crete/src/lib.rs
Normal file
11
crete/src/lib.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
pub mod cluster;
|
||||
pub mod node;
|
||||
pub mod patch;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use repo_path_lib::repo_dir;
|
||||
|
||||
fn base_dir() -> PathBuf {
|
||||
repo_dir().join("talos")
|
||||
}
|
||||
11
crete/src/main.rs
Normal file
11
crete/src/main.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
use crete::{cluster::Cluster, patch::Patch};
|
||||
|
||||
fn main() {
|
||||
// let patch = Patch::get("install-disk");
|
||||
//
|
||||
// let json = serde_json::to_string(&patch.resolve().unwrap()).unwrap();
|
||||
// println!("{json}")
|
||||
let cluster = Cluster::get("testing");
|
||||
|
||||
println!("{:#?}", cluster.nodes())
|
||||
}
|
||||
118
crete/src/node.rs
Normal file
118
crete/src/node.rs
Normal file
@@ -0,0 +1,118 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use optional_struct::{Applicable, optional_struct};
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::{
|
||||
base_dir,
|
||||
cluster::Cluster,
|
||||
patch::{OptionalPatches, Patch, Patches},
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
enum NodeType {
|
||||
Worker,
|
||||
ControlPlane,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
enum NodeArch {
|
||||
Amd64,
|
||||
}
|
||||
|
||||
#[optional_struct]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[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, Default)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
struct Install {
|
||||
auto: bool,
|
||||
disk: String,
|
||||
serial: Option<String>,
|
||||
}
|
||||
|
||||
#[optional_struct]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[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
|
||||
}
|
||||
}
|
||||
50
crete/src/patch.rs
Normal file
50
crete/src/patch.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use optional_struct::optional_struct;
|
||||
use serde::{Deserialize, Deserializer, Serialize};
|
||||
|
||||
use crate::base_dir;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Patch(String);
|
||||
|
||||
impl Patch {
|
||||
pub fn get(patch_name: impl AsRef<str>) -> Self {
|
||||
let mut path = base_dir().join("patches").join(patch_name.as_ref());
|
||||
path.add_extension("yaml");
|
||||
let content = std::fs::read_to_string(path).unwrap();
|
||||
|
||||
Self(content)
|
||||
}
|
||||
|
||||
pub fn resolve(&self) -> serde_yaml::Result<ResolvedPatch> {
|
||||
Ok(ResolvedPatch(serde_yaml::from_str(&self.0)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for Patch {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let name: &str = Deserialize::deserialize(deserializer)?;
|
||||
|
||||
Ok(Self::get(name))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct ResolvedPatch(serde_yaml::Value);
|
||||
|
||||
#[optional_struct]
|
||||
#[derive(Debug, Deserialize, Clone, PartialEq, Eq, Default)]
|
||||
#[serde(rename_all = "camelCase", deny_unknown_fields)]
|
||||
pub struct Patches {
|
||||
pub(crate) all: Vec<Patch>,
|
||||
pub(crate) control_plane: Vec<Patch>,
|
||||
}
|
||||
|
||||
impl Patches {
|
||||
pub(crate) fn extend(&mut self, other: Patches) {
|
||||
self.all.extend(other.all);
|
||||
self.control_plane.extend(other.control_plane);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user