#[allow(dead_code)] extern crate args; extern crate getopts; use args::{Args, ArgsError}; // use args::validations::{Order,OrderValidation}; use getopts::Occur; use tokio::runtime::Runtime; mod api; #[allow(unused)] struct Opts { registry: String, image: String, exclude: Vec, keep: i32, } fn main() { let mut rt = Runtime::new().unwrap(); let input_args = std::env::args().collect::>(); let _parsed = parse(&input_args).unwrap(); rt.block_on(async { let registry = api::registry::Registry { url: _parsed.registry.as_str(), }; let res = registry.get_repositories().await.unwrap(); if res.repositories.len() == 0 { return; } // println!("response :::: {:?}", res); let mut proc_images: Vec = Vec::new(); if _parsed.image.len() > 0 { if !res.repositories.contains(&_parsed.image) { eprintln!("image not in registry"); std::process::exit(1); } proc_images.push(_parsed.image); } else { proc_images = res.repositories.to_owned(); } // println!("proc images ::: {:?}", proc_images); for img in proc_images.into_iter() { println!("ProcImage: {}", img); let _repo_tags = registry.get_repository_tags(img.as_str()).await.unwrap(); let mut tags: Vec = Vec::new(); match _repo_tags.tags { Some(s) => { for x in s.iter() { if _parsed.exclude.contains(x) { continue; } let manifests = registry.get_repository_tag_manifest(img.as_str(), x).await; match manifests { Err(_) => continue, Ok(v) => tags.push(v), }; } } _ => continue, }; tags.sort_by(|a, b| b.ts.partial_cmp(&a.ts).unwrap()); // println!("{:?}", tags); let del_count: usize = if tags.len() > _parsed.keep as usize { _parsed.keep as usize } else { tags.len() }; tags.drain(0..del_count); println!("delete tag number : {}", tags.len()); for x in tags.iter() { if x.digest.len() == 0 { continue; } match registry .delete_repository_tag(img.as_str(), x.digest.as_str()) .await { Ok(_) => println!("delete {} success", x.tag), Err(_) => println!("delete {} fail", x.tag), }; } } }); } fn parse(input: &Vec) -> Result { let mut arg = Args::new("Registry Cleaner", "clean registry images"); arg.flag("h", "help", "print usage"); arg.option( "i", "image", "image name empty is all", "IMAGE", Occur::Optional, Some(String::from("")), ); arg.option( "e", "exclude", "exclude tag no delete", "EXCLUDE", Occur::Optional, None, ); arg.option( "r", "registry", "registry url", "REGISTRY", Occur::Optional, None, ); arg.option( "k", "keep", "keep tags number", "KEEP", Occur::Optional, None, ); arg.parse(input).unwrap(); let help: bool = arg.value_of("help").unwrap(); if help { let str = arg.full_usage(); eprintln!("{}", str); std::process::exit(1); } let exclude: Vec = match arg.values_of("exclude") { Ok(strs) => strs, Err(_) => vec![], }; let image: String = match arg.value_of("image") { Ok(v) => v, Err(_) => String::from(""), }; let url: String = arg.value_of("registry").unwrap(); let keep: i32 = match arg.value_of("keep") { Ok(v) => v, Err(_) => 10, }; let opts = Opts { image: image.clone(), exclude: exclude.clone(), registry: url, keep, }; Ok(opts) }