Skip to content

Commit

Permalink
fix: changes
Browse files Browse the repository at this point in the history
Signed-off-by: Christina Sørensen <[email protected]>
  • Loading branch information
cafkafk committed Mar 15, 2024
1 parent 7c26cf1 commit 62d69b1
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 127 deletions.
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ clap = { version = "4.5.1", features = ["cargo"] }
dns-lookup = "2.0.4"
domain = { version = "0.9.3", features = ["tokio", "resolv"] }
futures = "0.3.30"
gethostname = "0.4.3"
itertools = "0.12.1"
log = "0.4.21"
openssl = { version = "0.10.63" }
Expand All @@ -36,3 +37,4 @@ tokio = { version = "1.36.0", features = ["macros", "full"] }
clap = { version = "4.5.1", features = ["cargo"] }
clap_complete = "4"
clap_mangen = "0.2.20"
gethostname = "0.4.3"
2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
# For `nix develop`:
devShells.default = pkgs.mkShell {
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];
};

Expand Down
39 changes: 17 additions & 22 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,31 @@
//
// 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 {
use std::path::PathBuf;

command!()
.author(crate_authors!("\n"))
.arg(
Arg::new("all")
.short('a')
.long("all")
.help("Shows all fortunes, including unkind."),
)
.arg(
Arg::new("unkind")
.short('o')
.short('u')
.long("unkind")
.help("Shows only unkind fortunes."),
arg!(--cache <CACHE> "check a specific cache")
.required(false)
.default_value(DEFAULT_CACHE),
)
.arg(
Arg::new("find")
.short('m')
.long("find")
.value_name("pattern")
.help("Finds fortunes matching regex query."),
arg!(-n --name <HOST> "Hostname of machine.")
.required(false)
.value_parser(value_parser!(String)),
)
.arg(
Arg::new("length")
.short('n')
.long("length")
.help("Finds a fortune that is shorter than provided number."),
arg!(-c --config <FILE> "Path to NixOS config.")
.required(false)
.value_parser(value_parser!(PathBuf)),
)
.arg(arg!(-s --short ... "Shows a short aporism."))
.arg(arg!(-v --verbose ... "Verbosity level."))
}
155 changes: 51 additions & 104 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,145 +3,92 @@
//
// SPDX-License-Identifier: AGPL-3.0-only

use std::{
io,
net::{IpAddr, SocketAddr},
};
use std::{io, net::SocketAddr, env, sync::OnceLock};

use dns_lookup::lookup_host;
use futures::{future::join_all, stream, StreamExt};
use futures::future::join_all;
use itertools::Itertools;
use rayon::prelude::*;
use gethostname::gethostname;

#[allow(unused)]
use log::{debug, error, info, trace, warn};

use crate::nix::get_requisites;

mod cli;
mod net;
mod nix;

mod nix {

use serde_json::{Result, Value};
use std::{
path::Path,
process::{Command, Stdio},
str::Lines,
};

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()
}
}
/// The initial time to wait on http 104, in milliseconds
const SLIDE: u64 = 100;

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
}
}
}
}
const DEFAULT_CACHE: &str = "cache.nixos.org";

const HOST_NAME: OnceLock<String> = OnceLock::new();
const CACHE_URL: OnceLock<String> = OnceLock::new();

#[tokio::main(flavor = "multi_thread")]
async fn main() -> io::Result<()> {
pretty_env_logger::init();

let matches = cli::build_cli().get_matches();

let domain = "cache.nixos.org";
let ips: Vec<std::net::IpAddr> = lookup_host(domain).unwrap();
match matches
.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);

let domain_addr = SocketAddr::new(ips[0], 443);

let client = reqwest::Client::builder()
.resolve(domain, domain_addr)
.resolve(&domain, domain_addr)
.build()
.unwrap();

let binding = get_requisites("DBCAC");
let connection_buffer = binding
let binding = get_requisites(HOST_NAME.get().unwrap());

let tasks = binding
.lines()
.map(|line| line.to_owned())
.collect::<Vec<_>>();

// FIXME make constant
let slide = 100;

// FIXME we take ten just for testing
let tasks = connection_buffer
.collect::<Vec<_>>()
.into_iter()
.map(|hash| {
let client = client.clone();
let domain = domain.clone();
tokio::spawn(async move {
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();
Expand Down
26 changes: 26 additions & 0 deletions src/net.rs
Original file line number Diff line number Diff line change
@@ -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 changes: 53 additions & 0 deletions src/nix.rs
Original file line number Diff line number Diff line change
@@ -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()
}

0 comments on commit 62d69b1

Please sign in to comment.