170 lines
3.7 KiB
Rust
170 lines
3.7 KiB
Rust
#[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<String>,
|
|
keep: i32,
|
|
}
|
|
|
|
fn main() {
|
|
let mut rt = Runtime::new().unwrap();
|
|
|
|
let input_args = std::env::args().collect::<Vec<String>>();
|
|
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<String> = 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<api::registry::RepositoryTagManifest> = 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<String>) -> Result<Opts, ArgsError> {
|
|
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<String> = 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)
|
|
}
|