mirror of
https://github.com/edera-dev/krata.git
synced 2025-08-02 04:40:54 +00:00
hypha: convert to using anyhow for error handling
This commit is contained in:
parent
a1081ea79c
commit
eec213c712
@ -13,6 +13,7 @@ resolver = "2"
|
||||
version = "0.0.1"
|
||||
|
||||
[workspace.dependencies]
|
||||
anyhow = "1.0"
|
||||
thiserror = "1.0"
|
||||
log = "0.4.20"
|
||||
libc = "0.2"
|
||||
|
@ -5,6 +5,7 @@ edition = "2021"
|
||||
resolver = "2"
|
||||
|
||||
[dependencies]
|
||||
anyhow = { workspace = true }
|
||||
log = { workspace = true }
|
||||
env_logger = { workspace = true }
|
||||
zstd = { workspace = true }
|
||||
|
@ -1,5 +1,5 @@
|
||||
use anyhow::Result;
|
||||
use hypha::container::init::ContainerInit;
|
||||
use hypha::error::Result;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
env_logger::init();
|
||||
|
@ -1,6 +1,6 @@
|
||||
use anyhow::{anyhow, Result};
|
||||
use clap::{Parser, Subcommand};
|
||||
use hypha::ctl::Controller;
|
||||
use hypha::error::{HyphaError, Result};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
@ -48,8 +48,7 @@ fn main() -> Result<()> {
|
||||
|
||||
let args = ControllerArgs::parse();
|
||||
let store_path = if args.store == "auto" {
|
||||
default_store_path()
|
||||
.ok_or_else(|| HyphaError::new("unable to determine default store path"))
|
||||
default_store_path().ok_or_else(|| anyhow!("unable to determine default store path"))
|
||||
} else {
|
||||
Ok(PathBuf::from(args.store))
|
||||
}?;
|
||||
@ -57,7 +56,7 @@ fn main() -> Result<()> {
|
||||
let store_path = store_path
|
||||
.to_str()
|
||||
.map(|x| x.to_string())
|
||||
.ok_or_else(|| HyphaError::new("unable to convert store path to string"))?;
|
||||
.ok_or_else(|| anyhow!("unable to convert store path to string"))?;
|
||||
|
||||
let mut controller = Controller::new(store_path.clone())?;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::error::{HyphaError, Result};
|
||||
use anyhow::{anyhow, Result};
|
||||
use loopdev::{LoopControl, LoopDevice};
|
||||
use xenclient::BlockDeviceRef;
|
||||
|
||||
@ -16,11 +16,9 @@ impl AutoLoop {
|
||||
device.with().read_only(true).attach(file)?;
|
||||
let path = device
|
||||
.path()
|
||||
.ok_or(HyphaError::new("unable to get loop device path"))?
|
||||
.ok_or(anyhow!("unable to get loop device path"))?
|
||||
.to_str()
|
||||
.ok_or(HyphaError::new(
|
||||
"unable to convert loop device path to string",
|
||||
))?
|
||||
.ok_or(anyhow!("unable to convert loop device path to string",))?
|
||||
.to_string();
|
||||
let major = device.major()?;
|
||||
let minor = device.minor()?;
|
||||
|
@ -1,6 +1,5 @@
|
||||
use crate::error::Result;
|
||||
use crate::hypha_err;
|
||||
use crate::shared::LaunchInfo;
|
||||
use anyhow::{anyhow, Result};
|
||||
use log::trace;
|
||||
use nix::libc::dup2;
|
||||
use nix::unistd::execve;
|
||||
@ -69,7 +68,9 @@ impl ContainerInit {
|
||||
if let Some(cfg) = config.config() {
|
||||
self.run(cfg, &launch)?;
|
||||
} else {
|
||||
return hypha_err!("unable to determine what to execute, image config doesn't tell us");
|
||||
return Err(anyhow!(
|
||||
"unable to determine what to execute, image config doesn't tell us"
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::error::Result;
|
||||
use crate::image::ImageInfo;
|
||||
use crate::shared::LaunchInfo;
|
||||
use anyhow::Result;
|
||||
use backhand::{FilesystemWriter, NodeHeader};
|
||||
use log::trace;
|
||||
use std::fs;
|
||||
|
@ -2,11 +2,11 @@ pub mod cfgblk;
|
||||
|
||||
use crate::autoloop::AutoLoop;
|
||||
use crate::ctl::cfgblk::ConfigBlock;
|
||||
use crate::error::{HyphaError, Result};
|
||||
use crate::image::cache::ImageCache;
|
||||
use crate::image::name::ImageName;
|
||||
use crate::image::{ImageCompiler, ImageInfo};
|
||||
use crate::shared::LaunchInfo;
|
||||
use anyhow::{anyhow, Result};
|
||||
use loopdev::LoopControl;
|
||||
use std::io::{Read, Write};
|
||||
use std::path::PathBuf;
|
||||
@ -82,16 +82,16 @@ impl Controller {
|
||||
let image_squashfs_path = image_info
|
||||
.image_squashfs
|
||||
.to_str()
|
||||
.ok_or_else(|| HyphaError::new("failed to convert image squashfs path to string"))?;
|
||||
.ok_or_else(|| anyhow!("failed to convert image squashfs path to string"))?;
|
||||
|
||||
let cfgblk_dir_path = cfgblk
|
||||
.dir
|
||||
.to_str()
|
||||
.ok_or_else(|| HyphaError::new("failed to convert cfgblk directory path to string"))?;
|
||||
.ok_or_else(|| anyhow!("failed to convert cfgblk directory path to string"))?;
|
||||
let cfgblk_squashfs_path = cfgblk
|
||||
.file
|
||||
.to_str()
|
||||
.ok_or_else(|| HyphaError::new("failed to convert cfgblk squashfs path to string"))?;
|
||||
.ok_or_else(|| anyhow!("failed to convert cfgblk squashfs path to string"))?;
|
||||
|
||||
let image_squashfs_loop = self.autoloop.loopify(image_squashfs_path)?;
|
||||
let cfgblk_squashfs_loop = self.autoloop.loopify(cfgblk_squashfs_path)?;
|
||||
@ -149,17 +149,15 @@ impl Controller {
|
||||
let dom_path = store.get_domain_path(domid)?;
|
||||
let uuid = match store.read_string_optional(format!("{}/hypha/uuid", dom_path).as_str())? {
|
||||
None => {
|
||||
return Err(HyphaError::new(&format!(
|
||||
return Err(anyhow!(
|
||||
"domain {} was not found or not created by hypha",
|
||||
domid
|
||||
)))
|
||||
))
|
||||
}
|
||||
Some(value) => value,
|
||||
};
|
||||
if uuid.is_empty() {
|
||||
return Err(HyphaError::new(
|
||||
"unable to find hypha uuid based on the domain",
|
||||
));
|
||||
return Err(anyhow!("unable to find hypha uuid based on the domain",));
|
||||
}
|
||||
let uuid = Uuid::parse_str(&uuid)?;
|
||||
let loops = store.read_string(format!("{}/hypha/loops", dom_path).as_str())?;
|
||||
@ -235,8 +233,8 @@ impl Controller {
|
||||
None => continue,
|
||||
Some(value) => value,
|
||||
};
|
||||
let domid = u32::from_str(&domid_candidate)
|
||||
.map_err(|_| HyphaError::new("failed to parse domid"))?;
|
||||
let domid =
|
||||
u32::from_str(&domid_candidate).map_err(|_| anyhow!("failed to parse domid"))?;
|
||||
let uuid = Uuid::from_str(&uuid_string)?;
|
||||
let image = self
|
||||
.client
|
||||
|
@ -1,141 +0,0 @@
|
||||
use backhand::BackhandError;
|
||||
use cli_tables::TableError;
|
||||
use oci_spec::OciSpecError;
|
||||
use std::error::Error;
|
||||
use std::ffi::NulError;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::num::ParseIntError;
|
||||
use std::path::StripPrefixError;
|
||||
use xenclient::XenClientError;
|
||||
|
||||
pub type Result<T> = std::result::Result<T, HyphaError>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HyphaError {
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl HyphaError {
|
||||
pub fn new(msg: &str) -> HyphaError {
|
||||
HyphaError {
|
||||
message: msg.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for HyphaError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.message)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for HyphaError {
|
||||
fn description(&self) -> &str {
|
||||
&self.message
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! hypha_err {
|
||||
($($arg:tt)*) => {{
|
||||
use $crate::error::HyphaError;
|
||||
let text = std::fmt::format(format_args!($($arg)*));
|
||||
Err(HyphaError::new(text.as_str()))
|
||||
}}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for HyphaError {
|
||||
fn from(value: std::io::Error) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<XenClientError> for HyphaError {
|
||||
fn from(value: XenClientError) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<walkdir::Error> for HyphaError {
|
||||
fn from(value: walkdir::Error) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StripPrefixError> for HyphaError {
|
||||
fn from(value: StripPrefixError) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BackhandError> for HyphaError {
|
||||
fn from(value: BackhandError) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::Error> for HyphaError {
|
||||
fn from(value: serde_json::Error) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ureq::Error> for HyphaError {
|
||||
fn from(value: ureq::Error) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for HyphaError {
|
||||
fn from(value: ParseIntError) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<OciSpecError> for HyphaError {
|
||||
fn from(value: OciSpecError) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<url::ParseError> for HyphaError {
|
||||
fn from(value: url::ParseError) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::fmt::Error> for HyphaError {
|
||||
fn from(value: std::fmt::Error) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<uuid::Error> for HyphaError {
|
||||
fn from(value: uuid::Error) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<xenstore::error::Error> for HyphaError {
|
||||
fn from(value: xenstore::error::Error) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TableError> for HyphaError {
|
||||
fn from(value: TableError) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NulError> for HyphaError {
|
||||
fn from(value: NulError) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nix::Error> for HyphaError {
|
||||
fn from(value: nix::Error) -> Self {
|
||||
HyphaError::new(value.to_string().as_str())
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::error::{HyphaError, Result};
|
||||
use anyhow::{anyhow, Result};
|
||||
use oci_spec::image::{Arch, Descriptor, ImageIndex, ImageManifest, MediaType, Os, ToDockerV2S2};
|
||||
use std::io::copy;
|
||||
use std::io::{Read, Write};
|
||||
@ -63,21 +63,21 @@ impl RegistryClient {
|
||||
MediaType::ImageIndex.to_docker_v2s2()?,
|
||||
);
|
||||
let response = self.call(self.agent.get(url.as_str()).set("Accept", &accept))?;
|
||||
let content_type = response.header("Content-Type").ok_or_else(|| {
|
||||
HyphaError::new("registry response did not have a Content-Type header")
|
||||
})?;
|
||||
let content_type = response
|
||||
.header("Content-Type")
|
||||
.ok_or_else(|| anyhow!("registry response did not have a Content-Type header"))?;
|
||||
if content_type == MediaType::ImageIndex.to_string()
|
||||
|| content_type == MediaType::ImageIndex.to_docker_v2s2()?
|
||||
{
|
||||
let index = ImageIndex::from_reader(response.into_reader())?;
|
||||
let descriptor = self
|
||||
.pick_manifest(index)
|
||||
.ok_or_else(|| HyphaError::new("unable to pick manifest from index"))?;
|
||||
.ok_or_else(|| anyhow!("unable to pick manifest from index"))?;
|
||||
return self.get_manifest_with_digest(name, descriptor.digest());
|
||||
}
|
||||
let digest = response
|
||||
.header("Docker-Content-Digest")
|
||||
.ok_or_else(|| HyphaError::new("fetching manifest did not yield a content digest"))?
|
||||
.ok_or_else(|| anyhow!("fetching manifest did not yield a content digest"))?
|
||||
.to_string();
|
||||
let manifest = ImageManifest::from_reader(response.into_reader())?;
|
||||
Ok((manifest, digest))
|
||||
|
@ -2,10 +2,10 @@ pub mod cache;
|
||||
pub mod fetch;
|
||||
pub mod name;
|
||||
|
||||
use crate::error::{HyphaError, Result};
|
||||
use crate::image::cache::ImageCache;
|
||||
use crate::image::fetch::RegistryClient;
|
||||
use crate::image::name::ImageName;
|
||||
use anyhow::{anyhow, Result};
|
||||
use backhand::compression::Compressor;
|
||||
use backhand::{FilesystemCompressor, FilesystemWriter, NodeHeader};
|
||||
use flate2::read::GzDecoder;
|
||||
@ -160,10 +160,10 @@ impl ImageCompiler<'_> {
|
||||
let mut entry = entry?;
|
||||
let path = entry.path()?;
|
||||
let Some(name) = path.file_name() else {
|
||||
return Err(HyphaError::new("unable to get file name"));
|
||||
return Err(anyhow!("unable to get file name"));
|
||||
};
|
||||
let Some(name) = name.to_str() else {
|
||||
return Err(HyphaError::new("unable to get file name as string"));
|
||||
return Err(anyhow!("unable to get file name as string"));
|
||||
};
|
||||
|
||||
if name.starts_with(".wh.") {
|
||||
@ -214,7 +214,7 @@ impl ImageCompiler<'_> {
|
||||
} else if path.is_dir() {
|
||||
fs::remove_dir_all(&path)?;
|
||||
} else {
|
||||
return Err(HyphaError::new("opaque whiteout entry did not exist"));
|
||||
return Err(anyhow!("opaque whiteout entry did not exist"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -280,7 +280,7 @@ impl ImageCompiler<'_> {
|
||||
fn check_safe_path(&self, dst: &PathBuf, image_dir: &PathBuf) -> Result<()> {
|
||||
let resolved = path_clean::clean(dst);
|
||||
if !resolved.starts_with(image_dir) {
|
||||
return Err(HyphaError::new("layer attempts to work outside image dir"));
|
||||
return Err(anyhow!("layer attempts to work outside image dir"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -306,7 +306,7 @@ impl ImageCompiler<'_> {
|
||||
let mut file = File::create(&layer_path)?;
|
||||
let size = client.write_blob(&image.name, layer, &mut file)?;
|
||||
if layer.size() as u64 != size {
|
||||
return Err(HyphaError::new(
|
||||
return Err(anyhow!(
|
||||
"downloaded layer size differs from size in manifest",
|
||||
));
|
||||
}
|
||||
@ -323,11 +323,7 @@ impl ImageCompiler<'_> {
|
||||
MediaType::ImageLayer => LayerCompressionType::None,
|
||||
MediaType::ImageLayerGzip => LayerCompressionType::Gzip,
|
||||
MediaType::ImageLayerZstd => LayerCompressionType::Zstd,
|
||||
other => {
|
||||
return Err(HyphaError::new(
|
||||
format!("found layer with unknown media type: {}", other).as_str(),
|
||||
))
|
||||
}
|
||||
other => return Err(anyhow!("found layer with unknown media type: {}", other)),
|
||||
};
|
||||
Ok(LayerFile {
|
||||
digest: layer.digest().clone(),
|
||||
@ -346,7 +342,7 @@ impl ImageCompiler<'_> {
|
||||
.path()
|
||||
.strip_prefix(image_dir)?
|
||||
.to_str()
|
||||
.ok_or_else(|| HyphaError::new("failed to strip prefix of tmpdir"))?;
|
||||
.ok_or_else(|| anyhow!("failed to strip prefix of tmpdir"))?;
|
||||
let rel = format!("/{}", rel);
|
||||
trace!("ImageCompiler squash write {}", rel);
|
||||
let typ = entry.file_type();
|
||||
@ -373,7 +369,7 @@ impl ImageCompiler<'_> {
|
||||
let symlink = fs::read_link(entry.path())?;
|
||||
let symlink = symlink
|
||||
.to_str()
|
||||
.ok_or_else(|| HyphaError::new("failed to read symlink"))?;
|
||||
.ok_or_else(|| anyhow!("failed to read symlink"))?;
|
||||
writer.push_symlink(symlink, rel, header)?;
|
||||
} else if typ.is_dir() {
|
||||
writer.push_dir(rel, header)?;
|
||||
@ -393,7 +389,7 @@ impl ImageCompiler<'_> {
|
||||
let device = metadata.dev();
|
||||
writer.push_char_device(device as u32, rel, header)?;
|
||||
} else {
|
||||
return Err(HyphaError::new("invalid file type"));
|
||||
return Err(anyhow!("invalid file type"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -401,7 +397,7 @@ impl ImageCompiler<'_> {
|
||||
|
||||
let squash_file_path = squash_file
|
||||
.to_str()
|
||||
.ok_or_else(|| HyphaError::new("failed to convert squashfs string"))?;
|
||||
.ok_or_else(|| anyhow!("failed to convert squashfs string"))?;
|
||||
|
||||
let mut file = File::create(squash_file)?;
|
||||
trace!("ImageCompiler squash generate: {}", squash_file_path);
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::error::Result;
|
||||
use anyhow::Result;
|
||||
use std::fmt;
|
||||
use url::Url;
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
pub mod autoloop;
|
||||
pub mod container;
|
||||
pub mod ctl;
|
||||
pub mod error;
|
||||
pub mod image;
|
||||
mod shared;
|
||||
pub mod shared;
|
||||
|
Loading…
Reference in New Issue
Block a user