controller: implement enhanced image name format support

This commit is contained in:
Alex Zenla
2024-02-24 22:05:06 +00:00
parent 89e4f1a23d
commit 6511f2f0fa
5 changed files with 73 additions and 27 deletions

View File

@ -6,6 +6,9 @@ use std::ops::DerefMut;
use ureq::{Agent, Request, Response};
use url::Url;
const MANIFEST_PICKER_PLATFORM: Os = Os::Linux;
const MANIFEST_PICKER_ARCHITECTURE: Arch = Arch::Amd64;
pub struct RegistryClient {
agent: Agent,
url: Url,
@ -86,7 +89,9 @@ impl RegistryClient {
fn pick_manifest(&mut self, index: ImageIndex) -> Option<Descriptor> {
for item in index.manifests() {
if let Some(platform) = item.platform() {
if *platform.os() == Os::Linux && *platform.architecture() == Arch::Amd64 {
if *platform.os() == MANIFEST_PICKER_PLATFORM
&& *platform.architecture() == MANIFEST_PICKER_ARCHITECTURE
{
return Some(item.clone());
}
}

View File

@ -2,6 +2,9 @@ use anyhow::Result;
use std::fmt;
use url::Url;
const DOCKER_HUB_MIRROR: &str = "mirror.gcr.io";
const DEFAULT_IMAGE_TAG: &str = "latest";
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ImageName {
pub hostname: String,
@ -33,20 +36,39 @@ impl Default for ImageName {
impl ImageName {
pub fn parse(name: &str) -> Result<Self> {
let (hostname, name) = name
let full_name = name.to_string();
let name = full_name.clone();
let (mut hostname, mut name) = name
.split_once('/')
.unwrap_or(("registry-1.docker.io", name));
let (hostname, port) = if let Some((hostname, port)) = hostname.split_once(':') {
(hostname, Some(str::parse(port)?))
.map(|x| (x.0.to_string(), x.1.to_string()))
.unwrap_or_else(|| (DOCKER_HUB_MIRROR.to_string(), format!("library/{}", name)));
// heuristic to find any docker hub image formats
// that may be in the hostname format. for example:
// abc/xyz:latest will trigger this if check, but abc.io/xyz:latest will not,
// and neither will abc/hello/xyz:latest
if !hostname.contains('.') && full_name.chars().filter(|x| *x == '/').count() == 1 {
name = format!("{}/{}", hostname, name);
hostname = DOCKER_HUB_MIRROR.to_string();
}
let (hostname, port) = if let Some((hostname, port)) = hostname
.split_once(':')
.map(|x| (x.0.to_string(), x.1.to_string()))
{
(hostname, Some(str::parse(&port)?))
} else {
(hostname, None)
};
let (name, reference) = name.split_once(':').unwrap_or((name, "latest"));
let (name, reference) = name
.split_once(':')
.map(|x| (x.0.to_string(), x.1.to_string()))
.unwrap_or((name.to_string(), DEFAULT_IMAGE_TAG.to_string()));
Ok(ImageName {
hostname: hostname.to_string(),
hostname,
port,
name: name.to_string(),
reference: reference.to_string(),
name,
reference,
})
}