Merge pull request #30 from anthonyoteri/more-misc-cleanup

More miscellaneous code cleanup
This commit is contained in:
Anthony Oteri
2023-09-21 16:19:52 -04:00
committed by GitHub
5 changed files with 19 additions and 24 deletions
+9 -8
View File
@@ -36,24 +36,23 @@ use crate::error::ApiError;
/// configured `registry_url` base and the given `path`, or if there is an /// configured `registry_url` base and the given `path`, or if there is an
/// error deserializing the HTTP response body as JSON, or if there is an /// error deserializing the HTTP response body as JSON, or if there is an
/// error parsing the `Link` header value as an RFC5988 URL. /// error parsing the `Link` header value as an RFC5988 URL.
pub async fn fetch_all<T: for<'de> Deserialize<'de>>( pub async fn fetch_paginated<T: for<'de> Deserialize<'de>>(
base: &Url, origin: &Url,
path: &str, path: &str,
) -> Result<Vec<T>, ApiError> { ) -> Result<Vec<T>, ApiError> {
log::trace!("fetch_all({path:?})"); log::trace!("fetch_paginated(origin: {origin:?}, path: {path:?})");
let mut responses: Vec<T> = Vec::default(); let mut responses: Vec<T> = Vec::default();
let mut path = String::from(path); let mut next_path = String::from(path);
loop { loop {
log::debug!("GET {path:?}"); let url = origin.join(&next_path)?;
let url = base.join(&path)?;
let resp = reqwest::get(url).await?; let resp = reqwest::get(url).await?;
let headers = resp.headers().clone(); let headers = resp.headers().clone();
responses.push(resp.json().await?); responses.push(resp.json().await?);
if let Some(p) = parse_rfc5988(headers.get(http::header::LINK))? { if let Some(p) = parse_rfc5988(headers.get(http::header::LINK))? {
path = p; next_path = p;
} else { } else {
break; break;
} }
@@ -74,7 +73,7 @@ pub async fn fetch_all<T: for<'de> Deserialize<'de>>(
/// Returns and `ApiError` if there is a problem parsing contents of the /// Returns and `ApiError` if there is a problem parsing contents of the
/// supplied header value. /// supplied header value.
fn parse_rfc5988(header_value: Option<&http::HeaderValue>) -> Result<Option<String>, ApiError> { fn parse_rfc5988(header_value: Option<&http::HeaderValue>) -> Result<Option<String>, ApiError> {
log::trace!("parse_rfc5988({header_value:?})"); log::trace!("parse_rfc5988(header_value: {header_value:?})");
if let Some(link_value) = header_value { if let Some(link_value) = header_value {
let link_str = link_value.to_str()?; let link_str = link_value.to_str()?;
@@ -124,6 +123,8 @@ fn parse_rfc5988(header_value: Option<&http::HeaderValue>) -> Result<Option<Stri
/// * The above header is missing from the response. /// * The above header is missing from the response.
/// * A non 200 HTTP response status code is returned. /// * A non 200 HTTP response status code is returned.
pub fn parse_response_status(response: &reqwest::Response) -> Result<(), ApiError> { pub fn parse_response_status(response: &reqwest::Response) -> Result<(), ApiError> {
log::trace!("parse_response_status(response: {response:?})");
match response.status() { match response.status() {
http::StatusCode::OK => { http::StatusCode::OK => {
let headers = response.headers(); let headers = response.headers();
+1 -5
View File
@@ -33,10 +33,6 @@ pub(crate) struct Cli {
#[command(subcommand)] #[command(subcommand)]
pub command: Commands, pub command: Commands,
/// Optional configuration file override.
#[arg(short = 'c', long = "config")]
pub config: Option<OsString>,
#[arg( #[arg(
long = "log-level", long = "log-level",
require_equals = true, require_equals = true,
@@ -48,7 +44,7 @@ pub(crate) struct Cli {
)] )]
pub log_level: LogLevel, pub log_level: LogLevel,
/// The host or host:port for the Docker Registry /// The host or host:port or full base URL of the Docker Registry
pub registry: String, pub registry: String,
} }
+8 -10
View File
@@ -35,10 +35,10 @@ pub async fn catalog_handler(registry_url: &Url) -> Result<(), ApiError> {
repositories: Vec<String>, repositories: Vec<String>,
} }
log::trace!("catalog_handler()"); log::trace!("catalog_handler(registry_url: {registry_url:?})");
let path = "v2/_catalog"; let path = "v2/_catalog";
let responses: Vec<Response> = api::fetch_all(registry_url, path).await?; let responses: Vec<Response> = api::fetch_paginated(registry_url, path).await?;
let repository_list: Vec<&str> = responses let repository_list: Vec<&str> = responses
.iter() .iter()
.flat_map(|r| r.repositories.iter().map(String::as_str)) .flat_map(|r| r.repositories.iter().map(String::as_str))
@@ -66,10 +66,10 @@ pub async fn tags_handler(registry_url: &Url, name: &str) -> Result<(), ApiError
tags: Vec<String>, tags: Vec<String>,
} }
log::trace!("tags_handler(name: {name})"); log::trace!("tags_handler(registry_url: {registry_url:?}, name: {name})");
let path = format!("/v2/{name}/tags/list"); let path = format!("/v2/{name}/tags/list");
let responses: Vec<Response> = api::fetch_all(registry_url, &path).await?; let responses: Vec<Response> = api::fetch_paginated(registry_url, &path).await?;
let tag_list: Vec<&str> = responses let tag_list: Vec<&str> = responses
.iter() .iter()
.flat_map(|r| r.tags.iter().map(String::as_str)) .flat_map(|r| r.tags.iter().map(String::as_str))
@@ -90,7 +90,7 @@ pub async fn tags_handler(registry_url: &Url, name: &str) -> Result<(), ApiError
/// is a problem parsing the response from the Docker Registry API. /// is a problem parsing the response from the Docker Registry API.
#[allow(clippy::unused_async)] #[allow(clippy::unused_async)]
pub async fn show_handler(registry_url: &Url, image: &str, tag: &str) -> Result<(), ApiError> { pub async fn show_handler(registry_url: &Url, image: &str, tag: &str) -> Result<(), ApiError> {
log::trace!("show_handler(image: {image}, tag: {tag})"); log::trace!("show_handler(registry_url: {registry_url:?}, image: {image}, tag: {tag})");
let path = format!("/v2/{image}/manifests/{tag}"); let path = format!("/v2/{image}/manifests/{tag}");
let _url = registry_url.join(&path)?; let _url = registry_url.join(&path)?;
Ok(()) Ok(())
@@ -104,8 +104,8 @@ pub async fn show_handler(registry_url: &Url, image: &str, tag: &str) -> Result<
/// manifest digest, or if there is a problem deleting the manifest from the /// manifest digest, or if there is a problem deleting the manifest from the
/// Docker Registry API. /// Docker Registry API.
#[allow(clippy::unused_async)] #[allow(clippy::unused_async)]
pub async fn delete_handler(_registry_url: &Url, image: &str, tag: &str) -> Result<(), ApiError> { pub async fn delete_handler(registry_url: &Url, image: &str, tag: &str) -> Result<(), ApiError> {
log::trace!("delete_handler(image: {image}, tag: {tag})"); log::trace!("delete_handler(registry_url: {registry_url:?}, image: {image}, tag: {tag})");
todo!() todo!()
} }
@@ -118,14 +118,12 @@ pub async fn delete_handler(_registry_url: &Url, image: &str, tag: &str) -> Resu
/// Returns an `ApiError` if there is a problem communicating with the /// Returns an `ApiError` if there is a problem communicating with the
/// endpoint or if the required version is not supported. /// endpoint or if the required version is not supported.
pub async fn check_handler(registry_url: &Url) -> Result<(), ApiError> { pub async fn check_handler(registry_url: &Url) -> Result<(), ApiError> {
log::trace!("check_handler()"); log::trace!("check_handler(registry_url: {registry_url:?})");
let path = "/v2"; let path = "/v2";
let url = registry_url.join(path)?; let url = registry_url.join(path)?;
let response = reqwest::get(url).await?; let response = reqwest::get(url).await?;
api::parse_response_status(&response)?; api::parse_response_status(&response)?;
println!("Ok");
Ok(()) Ok(())
} }
+1
View File
@@ -16,6 +16,7 @@
#![allow(clippy::enum_variant_names)] #![allow(clippy::enum_variant_names)]
#![allow(clippy::module_name_repetitions)] #![allow(clippy::module_name_repetitions)]
use thiserror::Error; use thiserror::Error;
/// The common error type for this Application. /// The common error type for this Application.
-1
View File
@@ -21,7 +21,6 @@ use url::Url;
use crate::cli::Cli; use crate::cli::Cli;
use crate::cli::Commands; use crate::cli::Commands;
use crate::error::DredgeError; use crate::error::DredgeError;
mod api; mod api;