diff options
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 164 |
1 files changed, 18 insertions, 146 deletions
diff --git a/src/main.rs b/src/main.rs index 80b61a8..61987be 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,17 +4,17 @@ mod docker; mod manifest; mod dockerfile; mod metrics; +mod db; use crate::parser::*; use crate::version::{VersionPattern, CompareOutcome}; use crate::docker::DockerRef; use crate::manifest::ManifestFile; use crate::dockerfile::DockerfileFile; +use crate::db::{Db, SqliteDb}; use base64::prelude::*; use rand::distr::{Alphanumeric, SampleString}; -use rusqlite::Connection; -use rusqlite::OptionalExtension; use std::collections::HashMap; use std::ops::Range; use std::io::Read; @@ -244,7 +244,7 @@ struct FilePatch { } -fn update_images(db: &Connection, file: &str, auth: &mut Auth, img: DockerRef, edits: &mut Vec<FilePatch>) -> Result<(), String> { +fn update_images(db: &dyn Db, file: &str, auth: &mut Auth, img: DockerRef, edits: &mut Vec<FilePatch>) -> Result<(), String> { let registry = img.registry.map(|x| &file[x]).unwrap_or("registry.hub.docker.com"); let mut tag = img.tag.as_ref().map(|x| file[x.clone()].to_string()); let image = &file[img.image.clone()]; @@ -254,43 +254,17 @@ fn update_images(db: &Connection, file: &str, auth: &mut Auth, img: DockerRef, e let now = chrono::offset::Utc::now(); let cache_max_age = chrono::Duration::hours(24); - let query_result = { - let _timer = metrics::get().db_query_duration.start_timer(); - db.query_one(" - SELECT id, last_checked FROM images - WHERE registry = ?1 AND image = ?2 - ", (registry, image), |row| Ok(( - row.get::<_, i64>(0)?, - row.get::<_, chrono::DateTime<chrono::Utc>>(1)?, - ))).optional() - }; - - let (image_id, last_checked) = match query_result { - Ok(Some(x)) => x, - Ok(None) => { - { - let _timer = metrics::get().db_query_duration.start_timer(); - db.execute(" - INSERT INTO images(registry, image, last_checked) VALUES (?1, ?2, ?3) - ", (registry, &image, now)).unwrap(); - } - (db.last_insert_rowid(), now) + let (image_id, last_checked) = match db.get_image(registry, image) { + Some(x) => x, + None => { + let id = db.insert_image(registry, image, now); + (id, now) }, - Err(_x) => return Err("Database Failure".to_string()), }; let cache_stale = now - last_checked > cache_max_age; - let cached_tags: Vec<String> = { - let _timer = metrics::get().db_query_duration.start_timer(); - let mut stmt = db.prepare("SELECT tag FROM tags WHERE image_id = ?1 ORDER BY tag").unwrap(); - let mut rows = stmt.query((image_id,)).unwrap(); - let mut tags = vec![]; - while let Some(row) = rows.next().unwrap() { - tags.push(row.get(0).unwrap()); - } - tags - }; + let cached_tags: Vec<String> = db.get_tags_sorted(image_id); let (tags, cached_digest): (Vec<String>, Option<String>) = if cache_stale { let mut url = format!("/v2/{}/tags/list", &image); @@ -331,37 +305,23 @@ fn update_images(db: &Connection, file: &str, auth: &mut Auth, img: DockerRef, e for t in &fetched_tags { while existing.peek().is_some_and(|e| *e < t) { let gone = existing.next().unwrap(); - let _timer = metrics::get().db_query_duration.start_timer(); - db.execute("DELETE FROM tags WHERE image_id = ?1 AND tag = ?2", - (image_id, gone)).unwrap(); + db.delete_tag(image_id, gone); } if existing.peek() == Some(&t) { existing.next(); } else { - let _timer = metrics::get().db_query_duration.start_timer(); - db.execute("INSERT INTO tags(image_id, tag, fetched_at) VALUES (?1, ?2, ?3)", - (image_id, t, now)).unwrap(); + db.insert_tag(image_id, t, now); } } for gone in existing { - let _timer = metrics::get().db_query_duration.start_timer(); - db.execute("DELETE FROM tags WHERE image_id = ?1 AND tag = ?2", - (image_id, gone)).unwrap(); - } - { - let _timer = metrics::get().db_query_duration.start_timer(); - db.execute("UPDATE images SET last_checked = ?1 WHERE id = ?2", (now, image_id)).unwrap(); + db.delete_tag(image_id, gone); } + db.update_last_checked(image_id, now); (fetched_tags, None) } else { let tag_for_digest = tag.as_deref().unwrap_or("latest"); - let digest = { - let _timer = metrics::get().db_query_duration.start_timer(); - db.query_one(" - SELECT digest FROM tags WHERE image_id = ?1 AND tag = ?2 AND digest IS NOT NULL - ", (image_id, tag_for_digest), |row| row.get::<_, String>(0)).optional().unwrap() - }; + let digest = db.get_tag_digest(image_id, tag_for_digest); (cached_tags, digest) }; @@ -411,11 +371,7 @@ fn update_images(db: &Connection, file: &str, auth: &mut Auth, img: DockerRef, e let fetched = response.headers()["docker-content-digest"].to_str().unwrap().to_string(); - { - let _timer = metrics::get().db_query_duration.start_timer(); - db.execute("UPDATE tags SET digest = ?1, fetched_at = ?2 WHERE image_id = ?3 AND tag = ?4", - (&fetched, now, image_id, tag_for_digest)).unwrap(); - } + db.update_tag_digest(image_id, tag_for_digest, &fetched, now); fetched } @@ -523,7 +479,7 @@ fn is_yaml(path: &std::path::Path) -> bool { return false; } -fn run_tool(db: &Connection, auth: &mut Auth, repos: &Vec<Repository>, mut infile_paths: Vec<std::path::PathBuf>, overwrite: bool) { +fn run_tool(db: &dyn Db, auth: &mut Auth, repos: &Vec<Repository>, mut infile_paths: Vec<std::path::PathBuf>, overwrite: bool) { for repo in repos { if repo.dest.exists() { let mut gitcmd = std::process::Command::new("git"); @@ -809,95 +765,11 @@ fn main() { panic!("BAD ARGUMENTS"); } - let db = Connection::open(positional[0]).unwrap(); + let sqlite_db = SqliteDb::new(&std::path::PathBuf::from(positional[0])); if positional.len() > 1 { infile_paths.push(std::path::PathBuf::from(positional[1])); } - { - db.execute(" - CREATE TABLE IF NOT EXISTS migrations ( - id INTEGER PRIMARY KEY NOT NULL - ) - ", ()).unwrap(); - - let newest_migration: u32 = db.query_row(" - SELECT MAX(id) FROM migrations - ", [], |row| row.get::<_, Option<u32>>(0)).unwrap().unwrap_or(0); - - if newest_migration < 1 { - db.execute("INSERT INTO migrations(id) VALUES (?1)", (1, )).unwrap(); - } - - if newest_migration < 2 { - db.execute(" - CREATE TABLE known_images ( - id INTEGER PRIMARY KEY NOT NULL, - registry TEXT NOT NULL, - image TEXT NOT NULL, - tag TEXT NOT NULL - ) - ", ()).unwrap(); - - db.execute("INSERT INTO migrations(id) VALUES (?1)", (2, )).unwrap(); - } - - if newest_migration < 3 { - db.execute(" - ALTER TABLE known_images ADD COLUMN - discovered DATETIME NOT NULL - ", ()).unwrap(); - - db.execute("INSERT INTO migrations(id) VALUES (?1)", (3, )).unwrap(); - } - - if newest_migration < 4 { - // db.execute(" - // CREATE UNIQUE INDEX known_images__registry_image_tag - // ON known_images(registry, image, tag) - // ", ()).unwrap(); - - db.execute("INSERT INTO migrations(id) VALUES (?1)", (4, )).unwrap(); - } - - if newest_migration < 5 { - db.execute(" - CREATE TABLE images ( - id INTEGER PRIMARY KEY NOT NULL, - registry TEXT NOT NULL, - image TEXT NOT NULL, - last_checked DATETIME NOT NULL - ) - ", ()).unwrap(); - - db.execute(" - CREATE UNIQUE INDEX images__registry_image - ON images(registry, image) - ", ()).unwrap(); - - db.execute("INSERT INTO migrations(id) VALUES (?1)", (5, )).unwrap(); - } - - if newest_migration < 6 { - db.execute(" - CREATE TABLE tags ( - id INTEGER PRIMARY KEY, - image_id INTEGER NOT NULL REFERENCES images(id), - tag TEXT NOT NULL, - digest TEXT, - fetched_at DATETIME NOT NULL - ) - ", ()).unwrap(); - - db.execute(" - CREATE UNIQUE INDEX tags__image_id_tag - ON tags(image_id, tag) - ", ()).unwrap(); - - db.execute("INSERT INTO migrations(id) VALUES (?1)", (6, )).unwrap(); - } - } - let mut repos = vec![]; let workdir = std::env::current_dir().unwrap(); @@ -1090,7 +962,7 @@ fn main() { metrics::get().state.set(metrics::STATE_ACTIVE); let run_start = std::time::Instant::now(); - run_tool(&db, &mut auth, &repos, infile_paths.clone(), overwrite); + run_tool(&sqlite_db, &mut auth, &repos, infile_paths.clone(), overwrite); let run_duration = run_start.elapsed().as_secs_f64(); metrics::get().run_duration.set(run_duration); |
