git.delta.rocks / jrsonnet / refs/commits / 4340a04aa508

difftreelog

source

cmds/fleet/src/main.rs3.6 KiBsourcehistory
1pub mod cmds;2pub mod command;3pub mod host;4pub mod keys;56mod fleetdata;78use std::ffi::OsString;9use std::io;10use std::time::Duration;1112use anyhow::{anyhow, bail, Result};13use clap::Parser;1415use cmds::{build_systems::BuildSystems, info::Info, secrets::Secrets};16use host::{Config, FleetOpts};17use indicatif::{ProgressState, ProgressStyle};18use tokio::fs;19use tokio::process::Command;20use tracing::{info, metadata::LevelFilter};21use tracing_indicatif::IndicatifLayer;22use tracing_subscriber::{prelude::*, EnvFilter};2324#[derive(Parser)]25struct Prefetch {}26impl Prefetch {27	async fn run(&self, config: &Config) -> Result<()> {28		let mut prefetch_dir = config.directory.to_path_buf();29		prefetch_dir.push("prefetch");30		if !prefetch_dir.is_dir() {31			info!("nothing to prefetch: no prefetch directory");32			return Ok(());33		}34		for entry in std::fs::read_dir(&prefetch_dir)? {35			let entry = entry?;36			if !entry.metadata()?.is_file() {37				bail!("only files should exist in prefetch directory");38			}39			info!("prefetching {:?}", entry.file_name());40			let mut path = OsString::new();41			path.push("file://");42			path.push(entry.path());43			let status = Command::new("nix-prefetch-url").arg(path).status().await?;44			if !status.success() {45				bail!("failed with {status}");46			}47		}48		Ok(())49	}50}5152#[derive(Parser)]53enum Opts {54	/// Prepare systems for deployments55	BuildSystems(BuildSystems),56	/// Secret management57	#[clap(subcommand)]58	Secrets(Secrets),59	/// Upload prefetch directory to the nix store60	Prefetch(Prefetch),61	/// Config parsing62	Info(Info),63}6465#[derive(Parser)]66#[clap(version = "1.0", author)]67struct RootOpts {68	#[clap(flatten)]69	fleet_opts: FleetOpts,70	#[clap(subcommand)]71	command: Opts,72}7374async fn run_command(config: &Config, command: Opts) -> Result<()> {75	match command {76		Opts::BuildSystems(c) => c.run(config).await?,77		Opts::Secrets(s) => s.run(config).await?,78		Opts::Info(i) => i.run(config).await?,79		Opts::Prefetch(p) => p.run(config).await?,80	};81	Ok(())82}83fn elapsed_subsec(state: &ProgressState, writer: &mut dyn std::fmt::Write) {84	let _ = writer.write_str(&format!("{:?}", state.elapsed()));85}8687#[tokio::main]88async fn main() -> Result<()> {89	let indicatif_layer = IndicatifLayer::new().with_progress_style(90		ProgressStyle::with_template(91			"{color_start}{span_child_prefix} {span_name}{{{span_fields}}}{color_end} {wide_msg} {color_start}{pos:>7}/{len:7}{elapsed}{color_end}",92		)93		.unwrap()94		.with_key(95			"color_start",96			|state: &ProgressState, writer: &mut dyn std::fmt::Write| {97				let elapsed = state.elapsed();9899				if elapsed > Duration::from_secs(60) {100					// Red101					let _ = write!(writer, "\x1b[{}m", 1 + 30);102				} else if elapsed > Duration::from_secs(30) {103					// Yellow104					let _ = write!(writer, "\x1b[{}m", 3 + 30);105				}106			},107		)108		.with_key(109			"color_end",110			|state: &ProgressState, writer: &mut dyn std::fmt::Write| {111				if state.elapsed() > Duration::from_secs(30) {112					let _ = write!(writer, "\x1b[0m");113				}114			},115		),116	);117118	let filter = EnvFilter::from_default_env().add_directive(LevelFilter::INFO.into());119120	tracing_subscriber::registry()121		.with(122			tracing_subscriber::fmt::layer()123				.without_time()124				.with_target(false)125				.with_writer(indicatif_layer.get_stderr_writer())126				.with_filter(filter), // .withou,127		)128		.with(indicatif_layer)129		.init();130	info!("Starting");131	let mut os_args = std::env::args_os();132	let opts = RootOpts::parse_from((&mut os_args).take_while(|v| v != "--"));133	let config = opts.fleet_opts.build(os_args.collect()).await?;134135	match run_command(&config, opts.command).await {136		Ok(()) => {137			config.save()?;138			Ok(())139		}140		Err(e) => {141			let _ = config.save();142			Err(e)143		}144	}145}