fix: Run image as fallback for version retrieval
This commit is contained in:
parent
37a69df832
commit
20d1950530
6 changed files with 91 additions and 52 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -351,6 +351,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"blue-build-utils",
|
"blue-build-utils",
|
||||||
"bon",
|
"bon",
|
||||||
|
"cached",
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"colored",
|
"colored",
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ tempdir.workspace = true
|
||||||
bon.workspace = true
|
bon.workspace = true
|
||||||
users.workspace = true
|
users.workspace = true
|
||||||
uuid.workspace = true
|
uuid.workspace = true
|
||||||
|
cached = "0.53.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
rstest.workspace = true
|
rstest.workspace = true
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,19 @@
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Borrow,
|
borrow::Borrow,
|
||||||
collections::{hash_map::Entry, HashMap},
|
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
process::{ExitStatus, Output},
|
process::{ExitStatus, Output},
|
||||||
sync::{Mutex, RwLock},
|
sync::{Mutex, RwLock},
|
||||||
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use blue_build_utils::constants::IMAGE_VERSION_LABEL;
|
|
||||||
use bon::Builder;
|
use bon::Builder;
|
||||||
|
use cached::proc_macro::cached;
|
||||||
use clap::Args;
|
use clap::Args;
|
||||||
use log::{debug, info, trace};
|
use colored::Colorize;
|
||||||
use miette::{miette, Result};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
|
use log::{info, trace, warn};
|
||||||
|
use miette::{miette, IntoDiagnostic, Report, Result};
|
||||||
use oci_distribution::Reference;
|
use oci_distribution::Reference;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use opts::{GenerateImageNameOpts, GenerateTagsOpts};
|
use opts::{GenerateImageNameOpts, GenerateTagsOpts};
|
||||||
|
|
@ -24,6 +26,8 @@ use opts::{GenerateImageNameOpts, GenerateTagsOpts};
|
||||||
use sigstore_driver::SigstoreDriver;
|
use sigstore_driver::SigstoreDriver;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
use crate::logging::Logger;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
buildah_driver::BuildahDriver,
|
buildah_driver::BuildahDriver,
|
||||||
cosign_driver::CosignDriver,
|
cosign_driver::CosignDriver,
|
||||||
|
|
@ -75,9 +79,6 @@ static SELECTED_CI_DRIVER: Lazy<RwLock<Option<CiDriverType>>> = Lazy::new(|| RwL
|
||||||
/// UUID used to mark the current builds
|
/// UUID used to mark the current builds
|
||||||
static BUILD_ID: Lazy<Uuid> = Lazy::new(Uuid::new_v4);
|
static BUILD_ID: Lazy<Uuid> = Lazy::new(Uuid::new_v4);
|
||||||
|
|
||||||
/// The cached os versions
|
|
||||||
static OS_VERSION: Lazy<Mutex<HashMap<String, u64>>> = Lazy::new(|| Mutex::new(HashMap::new()));
|
|
||||||
|
|
||||||
/// Args for selecting the various drivers to use for runtime.
|
/// Args for selecting the various drivers to use for runtime.
|
||||||
///
|
///
|
||||||
/// If the args are left uninitialized, the program will determine
|
/// If the args are left uninitialized, the program will determine
|
||||||
|
|
@ -202,45 +203,7 @@ impl Driver {
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("Driver::get_os_version({oci_ref:#?})");
|
trace!("Driver::get_os_version({oci_ref:#?})");
|
||||||
let mut os_version_lock = OS_VERSION.lock().expect("Should lock");
|
get_version(oci_ref)
|
||||||
|
|
||||||
let entry = os_version_lock.get(&oci_ref.to_string());
|
|
||||||
|
|
||||||
let os_version = match entry {
|
|
||||||
None => {
|
|
||||||
info!("Retrieving OS version from {oci_ref}. This might take a bit");
|
|
||||||
let inspect_opts = GetMetadataOpts::builder()
|
|
||||||
.image(format!(
|
|
||||||
"{}/{}",
|
|
||||||
oci_ref.resolve_registry(),
|
|
||||||
oci_ref.repository()
|
|
||||||
))
|
|
||||||
.tag(oci_ref.tag().unwrap_or("latest"))
|
|
||||||
.build();
|
|
||||||
let inspection = Self::get_metadata(&inspect_opts)?;
|
|
||||||
|
|
||||||
let os_version = inspection.get_version().ok_or_else(|| {
|
|
||||||
miette!(
|
|
||||||
help = format!("Please check with the image author about using '{IMAGE_VERSION_LABEL}' to report the os version."),
|
|
||||||
"Unable to get the OS version from the labels"
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
trace!("os_version: {os_version}");
|
|
||||||
|
|
||||||
os_version
|
|
||||||
}
|
|
||||||
Some(os_version) => {
|
|
||||||
debug!("Found cached {os_version} for {oci_ref}");
|
|
||||||
*os_version
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Entry::Vacant(entry) = os_version_lock.entry(oci_ref.to_string()) {
|
|
||||||
trace!("Caching version {os_version} for {oci_ref}");
|
|
||||||
entry.insert(os_version);
|
|
||||||
}
|
|
||||||
drop(os_version_lock);
|
|
||||||
Ok(os_version)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_build_driver() -> BuildDriverType {
|
fn get_build_driver() -> BuildDriverType {
|
||||||
|
|
@ -264,6 +227,78 @@ impl Driver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cached(
|
||||||
|
result = true,
|
||||||
|
key = "String",
|
||||||
|
convert = "{ oci_ref.to_string() }",
|
||||||
|
sync_writes = true
|
||||||
|
)]
|
||||||
|
fn get_version(oci_ref: &Reference) -> Result<u64> {
|
||||||
|
info!("Retrieving OS version from {oci_ref}. This might take a bit");
|
||||||
|
let inspect_opts = GetMetadataOpts::builder()
|
||||||
|
.image(format!(
|
||||||
|
"{}/{}",
|
||||||
|
oci_ref.resolve_registry(),
|
||||||
|
oci_ref.repository()
|
||||||
|
))
|
||||||
|
.tag(oci_ref.tag().unwrap_or("latest"))
|
||||||
|
.build();
|
||||||
|
let os_version = Driver::get_metadata(&inspect_opts)
|
||||||
|
.and_then(|inspection| {
|
||||||
|
inspection.get_version().ok_or_else(|| {
|
||||||
|
miette!(
|
||||||
|
"Failed to parse version from metadata for {}",
|
||||||
|
oci_ref.to_string().bold()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.or_else(get_version_run_image(oci_ref))?;
|
||||||
|
trace!("os_version: {os_version}");
|
||||||
|
Ok(os_version)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_version_run_image(oci_ref: &Reference) -> impl FnOnce(Report) -> Result<u64> + '_ {
|
||||||
|
|err: Report| -> Result<u64> {
|
||||||
|
warn!("Unable to get version via image inspection due to error:\n{err:?}");
|
||||||
|
warn!(concat!(
|
||||||
|
"Pulling and running the image to retrieve the version. ",
|
||||||
|
"This will take a while..."
|
||||||
|
));
|
||||||
|
|
||||||
|
let progress = Logger::multi_progress().add(
|
||||||
|
ProgressBar::new_spinner()
|
||||||
|
.with_style(ProgressStyle::default_spinner())
|
||||||
|
.with_message(format!(
|
||||||
|
"Pulling image {} to get version",
|
||||||
|
oci_ref.to_string().bold()
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
progress.enable_steady_tick(Duration::from_millis(100));
|
||||||
|
|
||||||
|
let output = Driver::run_output(
|
||||||
|
&RunOpts::builder()
|
||||||
|
.image(oci_ref.to_string())
|
||||||
|
.args(bon::vec![
|
||||||
|
"/bin/bash",
|
||||||
|
"-c",
|
||||||
|
"grep -Po '(?<=VERSION_ID=)\\d+' /usr/lib/os-release",
|
||||||
|
])
|
||||||
|
.pull(true)
|
||||||
|
.remove(true)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.into_diagnostic()?;
|
||||||
|
|
||||||
|
progress.finish_and_clear();
|
||||||
|
Logger::multi_progress().remove(&progress);
|
||||||
|
|
||||||
|
String::from_utf8_lossy(&output.stdout)
|
||||||
|
.trim()
|
||||||
|
.parse()
|
||||||
|
.into_diagnostic()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_build_driver {
|
macro_rules! impl_build_driver {
|
||||||
($func:ident($($args:expr),*)) => {
|
($func:ident($($args:expr),*)) => {
|
||||||
match Self::get_build_driver() {
|
match Self::get_build_driver() {
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ use blue_build_utils::{
|
||||||
credentials::Credentials,
|
credentials::Credentials,
|
||||||
string_vec,
|
string_vec,
|
||||||
};
|
};
|
||||||
|
use colored::Colorize;
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
use log::{debug, info, trace, warn};
|
use log::{debug, info, trace, warn};
|
||||||
use miette::{bail, IntoDiagnostic, Result};
|
use miette::{bail, IntoDiagnostic, Result};
|
||||||
|
|
@ -317,7 +318,7 @@ impl InspectDriver for DockerDriver {
|
||||||
let progress = Logger::multi_progress().add(
|
let progress = Logger::multi_progress().add(
|
||||||
ProgressBar::new_spinner()
|
ProgressBar::new_spinner()
|
||||||
.with_style(ProgressStyle::default_spinner())
|
.with_style(ProgressStyle::default_spinner())
|
||||||
.with_message(format!("Inspecting metadata for {url}")),
|
.with_message(format!("Inspecting metadata for {}", url.bold())),
|
||||||
);
|
);
|
||||||
progress.enable_steady_tick(Duration::from_millis(100));
|
progress.enable_steady_tick(Duration::from_millis(100));
|
||||||
|
|
||||||
|
|
@ -330,7 +331,7 @@ impl InspectDriver for DockerDriver {
|
||||||
)
|
)
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
|
|
||||||
progress.finish();
|
progress.finish_and_clear();
|
||||||
Logger::multi_progress().remove(&progress);
|
Logger::multi_progress().remove(&progress);
|
||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
|
|
|
||||||
|
|
@ -194,7 +194,7 @@ impl InspectDriver for PodmanDriver {
|
||||||
let progress = Logger::multi_progress().add(
|
let progress = Logger::multi_progress().add(
|
||||||
ProgressBar::new_spinner()
|
ProgressBar::new_spinner()
|
||||||
.with_style(ProgressStyle::default_spinner())
|
.with_style(ProgressStyle::default_spinner())
|
||||||
.with_message(format!("Inspecting metadata for {url}")),
|
.with_message(format!("Inspecting metadata for {}", url.bold())),
|
||||||
);
|
);
|
||||||
progress.enable_steady_tick(Duration::from_millis(100));
|
progress.enable_steady_tick(Duration::from_millis(100));
|
||||||
|
|
||||||
|
|
@ -207,7 +207,7 @@ impl InspectDriver for PodmanDriver {
|
||||||
)
|
)
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
|
|
||||||
progress.finish();
|
progress.finish_and_clear();
|
||||||
Logger::multi_progress().remove(&progress);
|
Logger::multi_progress().remove(&progress);
|
||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{process::Stdio, time::Duration};
|
use std::{process::Stdio, time::Duration};
|
||||||
|
|
||||||
use blue_build_utils::cmd;
|
use blue_build_utils::cmd;
|
||||||
|
use colored::Colorize;
|
||||||
use indicatif::{ProgressBar, ProgressStyle};
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use miette::{bail, IntoDiagnostic, Result};
|
use miette::{bail, IntoDiagnostic, Result};
|
||||||
|
|
@ -24,7 +25,7 @@ impl InspectDriver for SkopeoDriver {
|
||||||
let progress = Logger::multi_progress().add(
|
let progress = Logger::multi_progress().add(
|
||||||
ProgressBar::new_spinner()
|
ProgressBar::new_spinner()
|
||||||
.with_style(ProgressStyle::default_spinner())
|
.with_style(ProgressStyle::default_spinner())
|
||||||
.with_message(format!("Inspecting metadata for {url}")),
|
.with_message(format!("Inspecting metadata for {}", url.bold())),
|
||||||
);
|
);
|
||||||
progress.enable_steady_tick(Duration::from_millis(100));
|
progress.enable_steady_tick(Duration::from_millis(100));
|
||||||
|
|
||||||
|
|
@ -34,7 +35,7 @@ impl InspectDriver for SkopeoDriver {
|
||||||
.output()
|
.output()
|
||||||
.into_diagnostic()?;
|
.into_diagnostic()?;
|
||||||
|
|
||||||
progress.finish();
|
progress.finish_and_clear();
|
||||||
Logger::multi_progress().remove(&progress);
|
Logger::multi_progress().remove(&progress);
|
||||||
|
|
||||||
if output.status.success() {
|
if output.status.success() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue