This repository has been archived on 2024-03-03. You can view files and clone it, but cannot push or open issues or pull requests.
clear-docker-images/src/images.rs

142 lines
3.8 KiB
Rust
Raw Normal View History

2022-03-06 04:26:23 +01:00
use chrono::NaiveDateTime;
2022-03-06 00:24:47 +01:00
use log::{error, warn};
use serde::{self, Deserialize, Deserializer};
use std::process::{exit, Command};
2022-02-20 23:06:15 +01:00
use crate::DateArgs;
2022-02-20 23:06:15 +01:00
use crate::DOCKER_BIN;
const GHCR_REPO: &str = "ghcr.io/datahearth/clear-docker-images";
const DOCKER_REPO: &str = "datahearth/clear-docker-images";
2022-02-20 23:06:15 +01:00
#[derive(Deserialize, Debug)]
struct Image {
// image ID
2022-02-20 23:06:15 +01:00
#[serde(rename = "ID")]
id: String,
// image repository
#[serde(rename = "Repository")]
repository: String,
// image tag
2022-02-20 23:06:15 +01:00
#[serde(rename = "Tag")]
tag: String,
// image creation date as UNIX timestamp
#[serde(deserialize_with = "deserialize_creation_date", rename = "CreatedAt")]
created_at: i64,
// image size in MB
#[serde(deserialize_with = "deserialize_size", rename = "Size")]
size: f32,
}
pub fn deserialize_creation_date<'de, D>(deserializer: D) -> Result<i64, D::Error>
where
D: Deserializer<'de>,
{
let date = String::deserialize(deserializer)?;
// format => 2021-01-01 00:00:00 +0100 CET
2022-03-06 04:26:23 +01:00
NaiveDateTime::parse_from_str(&date, "%Y-%m-%d %H:%M:%S %z %Z")
.map(|d| d.timestamp())
.map_err(serde::de::Error::custom)
}
pub fn deserialize_size<'de, D>(deserializer: D) -> Result<f32, D::Error>
where
D: Deserializer<'de>,
{
let size = String::deserialize(deserializer)?;
if size.contains("KB") {
size.replace("KB", "")
.parse::<f32>()
2022-03-06 04:29:22 +01:00
.map(|s| s / 1000.0)
.map_err(serde::de::Error::custom)
} else if size.contains("MB") {
size.replace("MB", "")
.parse::<f32>()
.map_err(serde::de::Error::custom)
} else if size.contains("GB") {
size.replace("GB", "")
.parse::<f32>()
2022-03-06 04:29:22 +01:00
.map(|s| s * 1000.0)
.map_err(serde::de::Error::custom)
} else {
Err(serde::de::Error::custom(format!(
"Unknown size identification: {}",
size,
)))
}
2022-02-20 23:06:15 +01:00
}
pub fn process_imgs(
repository: Option<String>,
tags: Vec<String>,
timestamps: DateArgs,
2022-02-20 23:06:15 +01:00
) -> (Vec<String>, f32) {
let mut ids = vec![];
let mut saved_size = 0.0;
2022-02-20 23:06:15 +01:00
for img in parse_imgs(repository) {
let image: Image = serde_json::from_str(&img).unwrap();
let del = timestamps
.stop
.map_or(timestamps.start > image.created_at, |stop| {
2022-03-06 04:26:23 +01:00
timestamps.start > image.created_at && image.created_at > stop
});
2022-02-20 23:06:15 +01:00
if del && (image.repository != GHCR_REPO && image.repository != DOCKER_REPO) {
2022-02-20 23:06:15 +01:00
if !tags.contains(&image.tag) {
ids.push(image.id);
saved_size += image.size
2022-02-20 23:06:15 +01:00
}
}
}
return (ids, saved_size);
}
fn get_images(repo: Option<String>) -> Vec<u8> {
let mut cmd = Command::new(DOCKER_BIN);
cmd.arg("images");
2022-03-05 16:25:59 +01:00
repo.map(|repo| cmd.arg(repo));
2022-02-20 23:06:15 +01:00
cmd.args(["--format", "{{json .}}"]);
match cmd.output() {
Ok(o) => {
if !o.status.success() {
2022-03-06 00:24:47 +01:00
error!(
2022-03-05 16:25:59 +01:00
"{}",
std::str::from_utf8(&o.stderr).expect("failed to parse STDERR to UTF-8")
);
2022-03-06 00:24:47 +01:00
error!("failed to retrieve docker images. Please checkout STDERR");
2022-02-20 23:06:15 +01:00
exit(1);
}
o.stdout
}
Err(e) => {
2022-03-06 00:24:47 +01:00
error!("docker command failed: {}", e);
2022-02-20 23:06:15 +01:00
exit(1);
}
}
}
fn parse_imgs(repository: Option<String>) -> Vec<String> {
let stdout = get_images(repository);
let output = String::from_utf8(stdout).unwrap_or_else(|e| {
2022-03-06 00:24:47 +01:00
error!("failed to parse docker output: {}", e);
2022-02-20 23:06:15 +01:00
exit(1);
});
2022-03-06 04:29:22 +01:00
let images: Vec<String> = output.lines().map(|s| s.to_string()).collect();
2022-02-20 23:06:15 +01:00
if images.len() == 0 {
2022-03-06 00:24:47 +01:00
warn!("No images found for current timestamp and/or repository");
2022-02-20 23:06:15 +01:00
}
return images;
}