mirror of
https://github.com/sergi0g/cup.git
synced 2025-11-17 17:43:37 -05:00
Finished basic functionality for multiple servers in the backend.
No special CLI or Liquid support yet and also no refresh support
This commit is contained in:
43
src/check.rs
43
src/check.rs
@@ -10,22 +10,27 @@ use crate::{
|
||||
registry::{check_auth, get_token},
|
||||
structs::{image::Image, update::Update},
|
||||
utils::request::{get_response_body, parse_json},
|
||||
warn,
|
||||
};
|
||||
|
||||
/// Fetches image data from other Cup servers
|
||||
async fn get_remote_updates(servers: &[String], client: &Client) -> Vec<Update> {
|
||||
/// Fetches image data from other Cup instances
|
||||
async fn get_remote_updates(servers: &FxHashMap<String, String>, client: &Client) -> Vec<Update> {
|
||||
let mut remote_images = Vec::new();
|
||||
|
||||
let futures: Vec<_> = servers
|
||||
let handles: Vec<_> = servers
|
||||
.iter()
|
||||
.map(|server| async {
|
||||
let url = if server.starts_with("http://") || server.starts_with("https://") {
|
||||
format!("{}/api/v3/json", server.trim_end_matches('/'))
|
||||
.map(|(name, url)| async {
|
||||
let url = if url.starts_with("http://") || url.starts_with("https://") {
|
||||
format!("{}/api/v3/json", url.trim_end_matches('/'))
|
||||
} else {
|
||||
format!("https://{}/api/v3/json", server.trim_end_matches('/'))
|
||||
format!("https://{}/api/v3/json", url.trim_end_matches('/'))
|
||||
};
|
||||
match client.get(&url, vec![], false).await {
|
||||
Ok(response) => {
|
||||
if response.status() != 200 {
|
||||
warn!("GET {}: Failed to fetch updates from server. Server returned invalid response code: {}",url,response.status());
|
||||
return Vec::new();
|
||||
}
|
||||
let json = parse_json(&get_response_body(response).await);
|
||||
if let Some(updates) = json["images"].as_array() {
|
||||
let mut server_updates: Vec<Update> = updates
|
||||
@@ -34,7 +39,7 @@ async fn get_remote_updates(servers: &[String], client: &Client) -> Vec<Update>
|
||||
.collect();
|
||||
// Add server origin to each image
|
||||
for update in &mut server_updates {
|
||||
update.server = Some(server.clone());
|
||||
update.server = Some(name.clone());
|
||||
update.status = update.get_status();
|
||||
}
|
||||
return server_updates;
|
||||
@@ -42,12 +47,15 @@ async fn get_remote_updates(servers: &[String], client: &Client) -> Vec<Update>
|
||||
|
||||
Vec::new()
|
||||
}
|
||||
Err(_) => Vec::new(),
|
||||
Err(e) => {
|
||||
warn!("Failed to fetch updates from server. {}", e);
|
||||
Vec::new()
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
for mut images in join_all(futures).await {
|
||||
for mut images in join_all(handles).await {
|
||||
remote_images.append(&mut images);
|
||||
}
|
||||
|
||||
@@ -64,8 +72,7 @@ pub async fn get_updates(references: &Option<Vec<String>>, config: &Config) -> V
|
||||
|
||||
// Add extra images from references
|
||||
if let Some(refs) = references {
|
||||
let image_refs: FxHashSet<&String> =
|
||||
images.iter().map(|image| &image.reference).collect();
|
||||
let image_refs: FxHashSet<&String> = images.iter().map(|image| &image.reference).collect();
|
||||
let extra = refs
|
||||
.iter()
|
||||
.filter(|&reference| !image_refs.contains(reference))
|
||||
@@ -85,10 +92,7 @@ pub async fn get_updates(references: &Option<Vec<String>>, config: &Config) -> V
|
||||
debug!(
|
||||
config.debug,
|
||||
"Checking {:?}",
|
||||
images
|
||||
.iter()
|
||||
.map(|image| &image.reference)
|
||||
.collect_vec()
|
||||
images.iter().map(|image| &image.reference).collect_vec()
|
||||
);
|
||||
|
||||
// Get a list of unique registries our images belong to. We are unwrapping the registry because it's guaranteed to be there.
|
||||
@@ -106,7 +110,10 @@ pub async fn get_updates(references: &Option<Vec<String>>, config: &Config) -> V
|
||||
let mut image_map: FxHashMap<&String, Vec<&Image>> = FxHashMap::default();
|
||||
|
||||
for image in &images {
|
||||
image_map.entry(&image.parts.registry).or_default().push(image);
|
||||
image_map
|
||||
.entry(&image.parts.registry)
|
||||
.or_default()
|
||||
.push(image);
|
||||
}
|
||||
|
||||
// Retrieve an authentication token (if required) for each registry.
|
||||
@@ -149,7 +156,7 @@ pub async fn get_updates(references: &Option<Vec<String>>, config: &Config) -> V
|
||||
.collect::<Vec<&String>>();
|
||||
|
||||
let mut handles = Vec::with_capacity(images.len());
|
||||
|
||||
|
||||
// Loop through images check for updates
|
||||
for image in &images {
|
||||
let is_ignored = ignored_registries.contains(&&image.parts.registry)
|
||||
|
||||
@@ -45,7 +45,7 @@ pub struct Config {
|
||||
pub images: ImageConfig,
|
||||
pub refresh_interval: Option<String>,
|
||||
pub registries: FxHashMap<String, RegistryConfig>,
|
||||
pub servers: Vec<String>,
|
||||
pub servers: FxHashMap<String, String>,
|
||||
pub socket: Option<String>,
|
||||
pub theme: Theme,
|
||||
}
|
||||
@@ -59,7 +59,7 @@ impl Config {
|
||||
images: ImageConfig::default(),
|
||||
refresh_interval: None,
|
||||
registries: FxHashMap::default(),
|
||||
servers: Vec::new(),
|
||||
servers: FxHashMap::default(),
|
||||
socket: None,
|
||||
theme: Theme::Default,
|
||||
}
|
||||
|
||||
@@ -14,7 +14,8 @@ use crate::{
|
||||
link::parse_link,
|
||||
request::{
|
||||
get_protocol, get_response_body, parse_json, parse_www_authenticate, to_bearer_string,
|
||||
}, time::{elapsed, now},
|
||||
},
|
||||
time::{elapsed, now},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -173,7 +174,9 @@ pub async fn get_latest_tag(
|
||||
let tag = tags.iter().max();
|
||||
debug!(
|
||||
config.debug,
|
||||
"Checked for tag update to {} in {}ms", image.reference, elapsed(start)
|
||||
"Checked for tag update to {} in {}ms",
|
||||
image.reference,
|
||||
elapsed(start)
|
||||
);
|
||||
match tag {
|
||||
Some(t) => {
|
||||
|
||||
@@ -188,7 +188,7 @@ impl Image {
|
||||
},
|
||||
time: self.time_ms,
|
||||
server: None,
|
||||
status: Status::Unknown(String::new())
|
||||
status: Status::Unknown(String::new()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
pub mod image;
|
||||
pub mod inspectdata;
|
||||
pub mod parts;
|
||||
pub mod status;
|
||||
pub mod version;
|
||||
pub mod update;
|
||||
pub mod parts;
|
||||
pub mod version;
|
||||
|
||||
@@ -40,4 +40,4 @@ impl Default for Status {
|
||||
fn default() -> Self {
|
||||
Self::Unknown("".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ pub struct Update {
|
||||
pub parts: Parts,
|
||||
pub result: UpdateResult,
|
||||
pub time: u32,
|
||||
#[serde(skip_serializing)]
|
||||
pub server: Option<String>,
|
||||
#[serde(skip_serializing, skip_deserializing)]
|
||||
pub status: Status,
|
||||
@@ -79,19 +78,15 @@ impl Update {
|
||||
Status::Unknown(s) => {
|
||||
if s.is_empty() {
|
||||
match self.result.has_update {
|
||||
Some(true) => {
|
||||
match &self.result.info {
|
||||
UpdateInfo::Version(info) => {
|
||||
match info.version_update_type.as_str() {
|
||||
"major" => Status::UpdateMajor,
|
||||
"minor" => Status::UpdateMinor,
|
||||
"patch" => Status::UpdatePatch,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
},
|
||||
UpdateInfo::Digest(_) => Status::UpdateAvailable,
|
||||
Some(true) => match &self.result.info {
|
||||
UpdateInfo::Version(info) => match info.version_update_type.as_str() {
|
||||
"major" => Status::UpdateMajor,
|
||||
"minor" => Status::UpdateMinor,
|
||||
"patch" => Status::UpdatePatch,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
},
|
||||
UpdateInfo::Digest(_) => Status::UpdateAvailable,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
Some(false) => Status::UpToDate,
|
||||
None => Status::Unknown(self.result.error.clone().unwrap()),
|
||||
@@ -99,8 +94,8 @@ impl Update {
|
||||
} else {
|
||||
self.status.clone()
|
||||
}
|
||||
},
|
||||
status => status.clone()
|
||||
}
|
||||
status => status.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,4 +4,4 @@ pub mod logging;
|
||||
pub mod reference;
|
||||
pub mod request;
|
||||
pub mod sort_update_vec;
|
||||
pub mod time;
|
||||
pub mod time;
|
||||
|
||||
@@ -35,8 +35,8 @@ pub fn get_protocol(
|
||||
} else {
|
||||
"https"
|
||||
}
|
||||
},
|
||||
None => "https"
|
||||
}
|
||||
None => "https",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user