3 Commits
Author SHA1 Message Date
Dreaded_X eaa925025d feat: Migrate to serde-saphyr
Committed / committed (pull_request) Successful in 1m9s
CI / cargo shear (pull_request) Successful in 6m12s
CI / prek (pull_request) Successful in 40m8s
CI / cargo shear (push) Successful in 8m30s
Audit / cargo audit (push) Failing after 13m17s
Release-plz / Release-plz Release (push) Successful in 5m15s
Release-plz / Release-plz PR (push) Failing after 5m34s
CI / prek (push) Successful in 22m43s
Fixes: #30
2026-10-21 08:09:25 +02:00
Dreaded_X 65ed7ab1d2 chore: Fix release-plz config
CI / cargo shear (push) Successful in 8m18s
Committed / committed (pull_request) Successful in 2m11s
CI / cargo shear (pull_request) Successful in 6m11s
CI / prek (pull_request) Successful in 30m45s
Release-plz / Release-plz Release (push) Successful in 4m45s
Release-plz / Release-plz PR (push) Failing after 6m25s
CI / prek (push) Successful in 27m25s
2026-10-21 07:52:48 +02:00
Dreaded_X 8e9c461a45 chore(deps): Upgrade all deps
Committed / committed (pull_request) Successful in 1m4s
CI / cargo shear (pull_request) Successful in 4m19s
CI / prek (pull_request) Successful in 19m18s
CI / cargo shear (push) Successful in 7m46s
Audit / cargo audit (push) Failing after 12m52s
Release-plz / Release-plz Release (push) Failing after 3m22s
Release-plz / Release-plz PR (push) Failing after 14m19s
CI / prek (push) Successful in 32m52s
2026-10-21 07:30:51 +02:00
11 changed files with 350 additions and 475 deletions
+9
View File
@@ -1,5 +1,14 @@
[workspace] [workspace]
pr_name = "chore(release): Release v{{ version }}" pr_name = "chore(release): Release v{{ version }}"
changelog_path = "./CHANGELOG.md"
[[package]]
name = "crete"
changelog_include = ["ipxe"]
[[package]]
name = "ipxe"
release = false
[[package]] [[package]]
name = "xtask" name = "xtask"
Generated
+302 -446
View File
File diff suppressed because it is too large Load Diff
+6 -5
View File
@@ -10,8 +10,8 @@ license = "GPL-3.0-or-later"
members = ["ipxe", "xtask"] members = ["ipxe", "xtask"]
[workspace.dependencies] [workspace.dependencies]
schemars = { version = "1.2.2", features = ["semver1"] } schemars = { version = "1.2.3", features = ["semver1"] }
serde_json = "1.0.151" serde_json = "1.0.154"
[dependencies] [dependencies]
async-walkdir = "2.2.0" async-walkdir = "2.2.0"
@@ -19,8 +19,8 @@ byteorder = "1.5.0"
clap = { version = "4.6.7", features = ["derive"] } clap = { version = "4.6.7", features = ["derive"] }
clap_complete = "4.6.11" clap_complete = "4.6.11"
futures = "0.3.34" futures = "0.3.34"
gix-discover = { version = "0.56.0", features = ["sha1"] } gix-discover = { version = "0.57.0", features = ["sha1"] }
minijinja = { version = "2.24.0", features = ["json", "loader"] } minijinja = { version = "3.0.1", features = ["json", "serde"] }
netascii = "0.1.0" netascii = "0.1.0"
num_enum = "0.7.6" num_enum = "0.7.6"
optional_struct = "0.5.2" optional_struct = "0.5.2"
@@ -34,11 +34,12 @@ serde = { version = "1.0.229", features = ["derive"] }
serde_json = { workspace = true } serde_json = { workspace = true }
serde_yaml = "0.9.34" serde_yaml = "0.9.34"
thiserror = "2.0.21" thiserror = "2.0.21"
tokio = { version = "1.52.1", features = ["full"] } tokio = { version = "1.54.0", features = ["full"] }
ipxe = { path = "./ipxe" } ipxe = { path = "./ipxe" }
axum = { version = "0.8.9", features = ["macros"] } axum = { version = "0.8.9", features = ["macros"] }
socket2 = "0.6.5" socket2 = "0.6.5"
socket-pktinfo = "0.4.1" socket-pktinfo = "0.4.1"
serde-saphyr = "2.0.0"
[lib] [lib]
test = false test = false
+1 -1
View File
@@ -102,7 +102,7 @@ impl Cluster {
path.add_extension("yaml"); path.add_extension("yaml");
let content = tokio::fs::read_to_string(path).await.unwrap(); let content = tokio::fs::read_to_string(path).await.unwrap();
let mut cluster: OptionalClusterDeserialize = serde_yaml::from_str(&content).unwrap(); let mut cluster: OptionalClusterDeserialize = serde_saphyr::from_str(&content).unwrap();
// For some reason apply on the cluster does not properly apply to the default settings... // For some reason apply on the cluster does not properly apply to the default settings...
// So we manually apply it here first // So we manually apply it here first
+13 -7
View File
@@ -4,8 +4,8 @@ use std::path::{Path, PathBuf};
use async_walkdir::WalkDir; use async_walkdir::WalkDir;
use futures::{Stream, StreamExt}; use futures::{Stream, StreamExt};
use minijinja::value::ViaDeserialize; use minijinja::syntax::SyntaxConfig;
use minijinja::{AutoEscape, Environment, path_loader}; use minijinja::{AutoEscape, Environment, path_loader, value};
use crate::{get_configs_path, get_talos_path}; use crate::{get_configs_path, get_talos_path};
@@ -19,21 +19,27 @@ pub struct PathEnvironment<'a> {
} }
fn apply_netmask( fn apply_netmask(
ip: ViaDeserialize<Ipv4Addr>, ip: value::Serde<Ipv4Addr>,
netmask: ViaDeserialize<Ipv4Addr>, netmask: value::Serde<Ipv4Addr>,
) -> Result<String, minijinja::Error> { ) -> Result<String, minijinja::Error> {
Ok((*ip & *netmask).to_string()) Ok((*ip & *netmask).to_string())
} }
pub fn configure_environment(env: &mut Environment) { pub fn configure_environment(env: &mut Environment) {
// Configure jinja // Configure jinja
env.set_trim_blocks(true); // Configure jinja
env.set_lstrip_blocks(true); env.set_syntax(
SyntaxConfig::builder()
.trim_blocks(true)
.lstrip_blocks(true)
.build()
.expect("Syntax config should be valid"),
);
env.set_undefined_behavior(minijinja::UndefinedBehavior::Strict); env.set_undefined_behavior(minijinja::UndefinedBehavior::Strict);
env.set_auto_escape_callback(|_| AutoEscape::None); env.set_auto_escape_callback(|_| AutoEscape::None);
// Add filters // Add filters
env.add_filter("to_prefix", |netmask: ViaDeserialize<Ipv4Addr>| { env.add_filter("to_prefix", |netmask: value::Serde<Ipv4Addr>| {
let mask = netmask.to_bits(); let mask = netmask.to_bits();
let prefix = mask.leading_ones(); let prefix = mask.leading_ones();
+2 -2
View File
@@ -1,7 +1,7 @@
use crete::cluster::Cluster; use crete::cluster::Cluster;
use crete::environment::configure_environment; use crete::environment::configure_environment;
use ipxe::IPXE_DIR; use ipxe::IPXE_DIR;
use minijinja::{Environment, context}; use minijinja::{Environment, context, value};
use regex::regex; use regex::regex;
pub async fn get_file( pub async fn get_file(
@@ -26,7 +26,7 @@ pub async fn get_file(
let clusters = Cluster::get_all().await; let clusters = Cluster::get_all().await;
let content = template let content = template
.render(context! { .render(context! {
clusters => clusters.values().collect::<Vec<_>>(), clusters => value::Serde(clusters.values().collect::<Vec<_>>()),
httpUrl => http_url.to_string() httpUrl => http_url.to_string()
}) })
.unwrap(); .unwrap();
+3 -3
View File
@@ -16,7 +16,7 @@ use crete::talosconfig::{get_current_context, set_context};
use crete::{get_configs_path, get_repo_path, set_repo_path, tftp}; use crete::{get_configs_path, get_repo_path, set_repo_path, tftp};
use futures::StreamExt; use futures::StreamExt;
use futures::future::join_all; use futures::future::join_all;
use minijinja::context; use minijinja::{context, value};
use crate::cli::{Cli, Commands, GlobalOpts}; use crate::cli::{Cli, Commands, GlobalOpts};
use crate::error::Error; use crate::error::Error;
@@ -44,8 +44,8 @@ async fn generate(opts: &GlobalOpts) -> Result<(), Error> {
let content = template let content = template
.render(context! { .render(context! {
clusters => clusters.values().collect::<Vec<_>>(), clusters => value::Serde(clusters.values().collect::<Vec<_>>()),
root => opts.repo root => value::Serde(&opts.repo)
}) })
.unwrap(); .unwrap();
+2 -2
View File
@@ -102,7 +102,7 @@ pub struct Node {
ntp: String, ntp: String,
install: Install, install: Install,
kernel_args: Vec<String>, kernel_args: Vec<String>,
patches: Patches<serde_yaml::Value>, patches: Patches<serde_json::Value>,
sops: Secret, sops: Secret,
} }
@@ -124,7 +124,7 @@ impl Node {
path.add_extension("yaml"); path.add_extension("yaml");
let content = tokio::fs::read_to_string(path).await.unwrap(); let content = tokio::fs::read_to_string(path).await.unwrap();
let node: OptionalNodeDeserialize = serde_yaml::from_str(&content).unwrap(); let node: OptionalNodeDeserialize = serde_saphyr::from_str(&content).unwrap();
// We want all vectors to be empty vectors by default // We want all vectors to be empty vectors by default
// Sadly we have to this manually // Sadly we have to this manually
+6 -6
View File
@@ -1,4 +1,4 @@
use minijinja::{Environment, context}; use minijinja::{Environment, context, value};
use optional_struct::optional_struct; use optional_struct::optional_struct;
use schemars::JsonSchema; use schemars::JsonSchema;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -21,7 +21,7 @@ async fn render(
env: &Environment<'static>, env: &Environment<'static>,
cluster: &Cluster, cluster: &Cluster,
node: &Node, node: &Node,
) -> Vec<serde_yaml::Value> { ) -> Vec<serde_json::Value> {
let env = env.clone(); let env = env.clone();
let cluster = cluster.clone(); let cluster = cluster.clone();
let node = node.clone(); let node = node.clone();
@@ -35,12 +35,12 @@ async fn render(
.get_template(&name) .get_template(&name)
.unwrap() .unwrap()
.render(context! { .render(context! {
node, node => value::Serde(&node),
cluster cluster => value::Serde(&cluster)
}) })
.unwrap(); .unwrap();
serde_yaml::from_str(&content).unwrap() serde_saphyr::from_str(&content).unwrap()
}) })
.collect() .collect()
}) })
@@ -64,7 +64,7 @@ impl Patches<String> {
env: &Environment<'static>, env: &Environment<'static>,
cluster: &Cluster, cluster: &Cluster,
node: &Node, node: &Node,
) -> Patches<serde_yaml::Value> { ) -> Patches<serde_json::Value> {
Patches { Patches {
all: render(self.all.clone(), env, cluster, node).await, all: render(self.all.clone(), env, cluster, node).await,
control_plane: render(self.control_plane.clone(), env, cluster, node).await, control_plane: render(self.control_plane.clone(), env, cluster, node).await,
+1 -1
View File
@@ -20,7 +20,7 @@ pub async fn get_current_context() -> Option<String> {
tokio::fs::read(&TalosConfig::merged_path()) tokio::fs::read(&TalosConfig::merged_path())
.await .await
.ok() .ok()
.and_then(|config| serde_yaml::from_slice(&config).ok()) .and_then(|config| serde_saphyr::from_slice(&config).ok())
.map(|config: TalosConfig| config.context) .map(|config: TalosConfig| config.context)
} }
+5 -2
View File
@@ -5,7 +5,7 @@ use std::time::Duration;
use socket_pktinfo::{PktInfo, PktInfoUdpSocket}; use socket_pktinfo::{PktInfo, PktInfoUdpSocket};
use socket2::Domain; use socket2::Domain;
use thiserror::Error; use thiserror::Error;
use tokio::io::unix::AsyncFd; use tokio::io::unix::{AsyncFd, AsyncFdRegisterError};
use tokio::net::UdpSocket; use tokio::net::UdpSocket;
use crate::tftp::packet::{ErrorCode, Mode, PACKET_SIZE}; use crate::tftp::packet::{ErrorCode, Mode, PACKET_SIZE};
@@ -29,6 +29,8 @@ pub enum Error {
UnexpectedPacket(Packet), UnexpectedPacket(Packet),
#[error("Timeout")] #[error("Timeout")]
Timeout, Timeout,
#[error("AsyncFd: {0}")]
AsyncFd(#[from] AsyncFdRegisterError<PktInfoUdpSocket>),
} }
pub async fn handle_connection<F, Fut>( pub async fn handle_connection<F, Fut>(
@@ -161,7 +163,8 @@ where
let addr: SocketAddr = (ip, 69).into(); let addr: SocketAddr = (ip, 69).into();
socket.bind(&addr.into())?; socket.bind(&addr.into())?;
let async_fd = AsyncFd::new(socket)?; let async_fd = unsafe { AsyncFd::register(socket)? };
let mut buf = [0u8; PACKET_SIZE]; let mut buf = [0u8; PACKET_SIZE];
println!("Tftp server started on {addr}"); println!("Tftp server started on {addr}");