fix: changes
Signed-off-by: Christina Sørensen <christina@cafkafk.com>
This commit is contained in:
parent
7c26cf1437
commit
62d69b12da
7 changed files with 160 additions and 126 deletions
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -540,6 +540,16 @@ dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gethostname"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-targets 0.48.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getopts"
|
name = "getopts"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
|
@ -870,6 +880,7 @@ dependencies = [
|
||||||
"dns-lookup",
|
"dns-lookup",
|
||||||
"domain",
|
"domain",
|
||||||
"futures",
|
"futures",
|
||||||
|
"gethostname",
|
||||||
"itertools",
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"openssl",
|
"openssl",
|
||||||
|
|
|
@ -21,6 +21,7 @@ clap = { version = "4.5.1", features = ["cargo"] }
|
||||||
dns-lookup = "2.0.4"
|
dns-lookup = "2.0.4"
|
||||||
domain = { version = "0.9.3", features = ["tokio", "resolv"] }
|
domain = { version = "0.9.3", features = ["tokio", "resolv"] }
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
gethostname = "0.4.3"
|
||||||
itertools = "0.12.1"
|
itertools = "0.12.1"
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
openssl = { version = "0.10.63" }
|
openssl = { version = "0.10.63" }
|
||||||
|
@ -36,3 +37,4 @@ tokio = { version = "1.36.0", features = ["macros", "full"] }
|
||||||
clap = { version = "4.5.1", features = ["cargo"] }
|
clap = { version = "4.5.1", features = ["cargo"] }
|
||||||
clap_complete = "4"
|
clap_complete = "4"
|
||||||
clap_mangen = "0.2.20"
|
clap_mangen = "0.2.20"
|
||||||
|
gethostname = "0.4.3"
|
||||||
|
|
|
@ -121,7 +121,7 @@
|
||||||
# For `nix develop`:
|
# For `nix develop`:
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
inherit (self.checks.${system}.pre-commit-check) shellHook;
|
inherit (self.checks.${system}.pre-commit-check) shellHook;
|
||||||
inputsFrom = [ self.packages.${system}.default];
|
inputsFrom = [self.packages.${system}.default];
|
||||||
nativeBuildInputs = with pkgs; [rustup toolchain just zip reuse];
|
nativeBuildInputs = with pkgs; [rustup toolchain just zip reuse];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
39
src/cli.rs
39
src/cli.rs
|
@ -3,36 +3,31 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
use clap::{arg, command, crate_authors, Arg, Command};
|
use std::{cell::OnceCell, sync::OnceLock};
|
||||||
|
|
||||||
|
use clap::{arg, command, crate_authors, value_parser, Arg, Command};
|
||||||
|
|
||||||
|
const DEFAULT_CACHE: &str = "cache.nixos.org";
|
||||||
|
|
||||||
pub fn build_cli() -> Command {
|
pub fn build_cli() -> Command {
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
command!()
|
command!()
|
||||||
.author(crate_authors!("\n"))
|
.author(crate_authors!("\n"))
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("all")
|
arg!(--cache <CACHE> "check a specific cache")
|
||||||
.short('a')
|
.required(false)
|
||||||
.long("all")
|
.default_value(DEFAULT_CACHE),
|
||||||
.help("Shows all fortunes, including unkind."),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("unkind")
|
arg!(-n --name <HOST> "Hostname of machine.")
|
||||||
.short('o')
|
.required(false)
|
||||||
.short('u')
|
.value_parser(value_parser!(String)),
|
||||||
.long("unkind")
|
|
||||||
.help("Shows only unkind fortunes."),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("find")
|
arg!(-c --config <FILE> "Path to NixOS config.")
|
||||||
.short('m')
|
.required(false)
|
||||||
.long("find")
|
.value_parser(value_parser!(PathBuf)),
|
||||||
.value_name("pattern")
|
|
||||||
.help("Finds fortunes matching regex query."),
|
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(arg!(-v --verbose ... "Verbosity level."))
|
||||||
Arg::new("length")
|
|
||||||
.short('n')
|
|
||||||
.long("length")
|
|
||||||
.help("Finds a fortune that is shorter than provided number."),
|
|
||||||
)
|
|
||||||
.arg(arg!(-s --short ... "Shows a short aporism."))
|
|
||||||
}
|
}
|
||||||
|
|
153
src/main.rs
153
src/main.rs
|
@ -3,15 +3,12 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: AGPL-3.0-only
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
use std::{
|
use std::{io, net::SocketAddr, env, sync::OnceLock};
|
||||||
io,
|
|
||||||
net::{IpAddr, SocketAddr},
|
|
||||||
};
|
|
||||||
|
|
||||||
use dns_lookup::lookup_host;
|
use dns_lookup::lookup_host;
|
||||||
use futures::{future::join_all, stream, StreamExt};
|
use futures::future::join_all;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rayon::prelude::*;
|
use gethostname::gethostname;
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
use log::{debug, error, info, trace, warn};
|
use log::{debug, error, info, trace, warn};
|
||||||
|
@ -19,93 +16,16 @@ use log::{debug, error, info, trace, warn};
|
||||||
use crate::nix::get_requisites;
|
use crate::nix::get_requisites;
|
||||||
|
|
||||||
mod cli;
|
mod cli;
|
||||||
|
mod net;
|
||||||
|
mod nix;
|
||||||
|
|
||||||
mod nix {
|
/// The initial time to wait on http 104, in milliseconds
|
||||||
|
const SLIDE: u64 = 100;
|
||||||
|
|
||||||
use serde_json::{Result, Value};
|
const DEFAULT_CACHE: &str = "cache.nixos.org";
|
||||||
use std::{
|
|
||||||
path::Path,
|
|
||||||
process::{Command, Stdio},
|
|
||||||
str::Lines,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn get_requisites(host: &str) -> String {
|
const HOST_NAME: OnceLock<String> = OnceLock::new();
|
||||||
let get_drv_path = Command::new("nix")
|
const CACHE_URL: OnceLock<String> = OnceLock::new();
|
||||||
.current_dir(Path::new("/home/ces/org/src/git/afk-nixos"))
|
|
||||||
.env("NIXPKGS_ALLOW_INSECURE", "1")
|
|
||||||
.args([
|
|
||||||
"build",
|
|
||||||
"--impure",
|
|
||||||
"--quiet",
|
|
||||||
&format!(
|
|
||||||
"./#nixosConfigurations.{}.config.system.build.toplevel",
|
|
||||||
host
|
|
||||||
),
|
|
||||||
"--dry-run",
|
|
||||||
"--json",
|
|
||||||
"--option",
|
|
||||||
"eval-cache",
|
|
||||||
"true",
|
|
||||||
])
|
|
||||||
.output()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let drv_path_json: Value =
|
|
||||||
serde_json::from_str(&String::from_utf8(get_drv_path.stdout).unwrap()).unwrap();
|
|
||||||
let drv_path = drv_path_json[0]["drvPath"].clone();
|
|
||||||
|
|
||||||
println!("drv_path: {}", &drv_path);
|
|
||||||
|
|
||||||
let get_drv_requisites = Command::new("nix-store")
|
|
||||||
.args(["--query", "--requisites", drv_path.as_str().unwrap()])
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
.unwrap();
|
|
||||||
let drv_requisites_remove_base = Command::new("cut")
|
|
||||||
.args(["-d", "/", "-f4"])
|
|
||||||
.stdin(Stdio::from(get_drv_requisites.stdout.unwrap()))
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
.unwrap();
|
|
||||||
let drv_requisites_to_hash = Command::new("cut")
|
|
||||||
.args(["-d", "-", "-f1"])
|
|
||||||
.stdin(Stdio::from(drv_requisites_remove_base.stdout.unwrap()))
|
|
||||||
.stdout(Stdio::piped())
|
|
||||||
.spawn()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
String::from_utf8(drv_requisites_to_hash.wait_with_output().unwrap().stdout).unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod net {
|
|
||||||
use std::{net::SocketAddr, time::Duration};
|
|
||||||
|
|
||||||
use async_recursion::async_recursion;
|
|
||||||
use reqwest::{Client, ClientBuilder, StatusCode};
|
|
||||||
use tokio::time::sleep;
|
|
||||||
|
|
||||||
#[async_recursion]
|
|
||||||
pub async fn nar_exists(client: Client, domain: &str, hash: &str, slide: u64) -> usize {
|
|
||||||
let response = client
|
|
||||||
.head(format!("https://{domain}/{hash}.narinfo"))
|
|
||||||
.send()
|
|
||||||
.await;
|
|
||||||
|
|
||||||
match response {
|
|
||||||
Ok(response) if response.status().as_u16() == 200 => 1,
|
|
||||||
Ok(response) if response.status().as_u16() == 404 => 0,
|
|
||||||
_ => {
|
|
||||||
// We're so fast now we get rate limited.
|
|
||||||
//
|
|
||||||
// Writng an actual sliding window seems kinda hard,
|
|
||||||
// so we do this instead.
|
|
||||||
sleep(Duration::from_millis(slide)).await;
|
|
||||||
nar_exists(client, domain, hash, slide * 2).await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main(flavor = "multi_thread")]
|
#[tokio::main(flavor = "multi_thread")]
|
||||||
async fn main() -> io::Result<()> {
|
async fn main() -> io::Result<()> {
|
||||||
|
@ -113,35 +33,62 @@ async fn main() -> io::Result<()> {
|
||||||
|
|
||||||
let matches = cli::build_cli().get_matches();
|
let matches = cli::build_cli().get_matches();
|
||||||
|
|
||||||
let domain = "cache.nixos.org";
|
match matches
|
||||||
let ips: Vec<std::net::IpAddr> = lookup_host(domain).unwrap();
|
.get_one::<u8>("verbose")
|
||||||
|
.expect("Count's are defaulted")
|
||||||
|
{
|
||||||
|
0 => env::set_var("RUST_LOG", "error"),
|
||||||
|
1 => env::set_var("RUST_LOG", "warn"),
|
||||||
|
2 => env::set_var("RUST_LOG", "info"),
|
||||||
|
3 => env::set_var("RUST_LOG", "debug"),
|
||||||
|
4 => env::set_var("RUST_LOG", "trace"),
|
||||||
|
_ => {
|
||||||
|
trace!("More than four -v flags don't increase log level.");
|
||||||
|
env::set_var("RUST_LOG", "trace")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(name) = matches.get_one::<String>("name") {
|
||||||
|
HOST_NAME.get_or_init(|| name.to_owned());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
HOST_NAME.get_or_init(|| gethostname().into_string().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(cache) = matches.get_one::<String>("cache") {
|
||||||
|
trace!("Got cache argument: {cache}");
|
||||||
|
CACHE_URL.get_or_init(|| cache.to_owned());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace!("No cache argument, using default: {}", DEFAULT_CACHE.to_string());
|
||||||
|
CACHE_URL.get_or_init(|| DEFAULT_CACHE.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
let domain = CACHE_URL.get().unwrap().to_owned();
|
||||||
|
let ips: Vec<std::net::IpAddr> = lookup_host(&domain).unwrap();
|
||||||
|
|
||||||
debug!("{:#?}", &ips);
|
debug!("{:#?}", &ips);
|
||||||
|
|
||||||
let domain_addr = SocketAddr::new(ips[0], 443);
|
let domain_addr = SocketAddr::new(ips[0], 443);
|
||||||
|
|
||||||
let client = reqwest::Client::builder()
|
let client = reqwest::Client::builder()
|
||||||
.resolve(domain, domain_addr)
|
.resolve(&domain, domain_addr)
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let binding = get_requisites("DBCAC");
|
let binding = get_requisites(HOST_NAME.get().unwrap());
|
||||||
let connection_buffer = binding
|
|
||||||
|
let tasks = binding
|
||||||
.lines()
|
.lines()
|
||||||
.map(|line| line.to_owned())
|
.map(|line| line.to_owned())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>()
|
||||||
|
|
||||||
// FIXME make constant
|
|
||||||
let slide = 100;
|
|
||||||
|
|
||||||
// FIXME we take ten just for testing
|
|
||||||
let tasks = connection_buffer
|
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|hash| {
|
.map(|hash| {
|
||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
|
let domain = domain.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
info!("connecting to {domain} {domain_addr:#?} for {hash}");
|
info!("connecting to {domain} {domain_addr:#?} for {hash}");
|
||||||
net::nar_exists(client, domain, &hash, slide).await
|
net::nar_exists(client, &domain, &hash, SLIDE).await
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
|
|
26
src/net.rs
Normal file
26
src/net.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use async_recursion::async_recursion;
|
||||||
|
use reqwest::Client;
|
||||||
|
use tokio::time::sleep;
|
||||||
|
|
||||||
|
#[async_recursion]
|
||||||
|
pub async fn nar_exists(client: Client, domain: &str, hash: &str, slide: u64) -> usize {
|
||||||
|
let response = client
|
||||||
|
.head(format!("https://{domain}/{hash}.narinfo"))
|
||||||
|
.send()
|
||||||
|
.await;
|
||||||
|
|
||||||
|
match response {
|
||||||
|
Ok(response) if response.status().as_u16() == 200 => 1,
|
||||||
|
Ok(response) if response.status().as_u16() == 404 => 0,
|
||||||
|
_ => {
|
||||||
|
// We're so fast now we get rate limited.
|
||||||
|
//
|
||||||
|
// Writng an actual sliding window seems kinda hard,
|
||||||
|
// so we do this instead.
|
||||||
|
sleep(Duration::from_millis(slide)).await;
|
||||||
|
nar_exists(client, domain, hash, slide * 2).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
53
src/nix.rs
Normal file
53
src/nix.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use serde_json::Value;
|
||||||
|
use std::{
|
||||||
|
path::Path,
|
||||||
|
process::{Command, Stdio},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn get_requisites(host: &str) -> String {
|
||||||
|
let get_drv_path = Command::new("nix")
|
||||||
|
.current_dir(Path::new("/home/ces/org/src/git/afk-nixos"))
|
||||||
|
.env("NIXPKGS_ALLOW_INSECURE", "1")
|
||||||
|
.args([
|
||||||
|
"build",
|
||||||
|
"--impure",
|
||||||
|
"--quiet",
|
||||||
|
&format!(
|
||||||
|
"./#nixosConfigurations.{}.config.system.build.toplevel",
|
||||||
|
host
|
||||||
|
),
|
||||||
|
"--dry-run",
|
||||||
|
"--json",
|
||||||
|
"--option",
|
||||||
|
"eval-cache",
|
||||||
|
"true",
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let drv_path_json: Value =
|
||||||
|
serde_json::from_str(&String::from_utf8(get_drv_path.stdout).unwrap()).unwrap();
|
||||||
|
let drv_path = drv_path_json[0]["drvPath"].clone();
|
||||||
|
|
||||||
|
println!("drv_path: {}", &drv_path);
|
||||||
|
|
||||||
|
let get_drv_requisites = Command::new("nix-store")
|
||||||
|
.args(["--query", "--requisites", drv_path.as_str().unwrap()])
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
let drv_requisites_remove_base = Command::new("cut")
|
||||||
|
.args(["-d", "/", "-f4"])
|
||||||
|
.stdin(Stdio::from(get_drv_requisites.stdout.unwrap()))
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
let drv_requisites_to_hash = Command::new("cut")
|
||||||
|
.args(["-d", "-", "-f1"])
|
||||||
|
.stdin(Stdio::from(drv_requisites_remove_base.stdout.unwrap()))
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
String::from_utf8(drv_requisites_to_hash.wait_with_output().unwrap().stdout).unwrap()
|
||||||
|
}
|
Loading…
Reference in a new issue