diff --git a/src/fs-gen/src/cli_args.rs b/src/fs-gen/src/cli_args.rs index 718f80c..a736113 100644 --- a/src/fs-gen/src/cli_args.rs +++ b/src/fs-gen/src/cli_args.rs @@ -1,6 +1,6 @@ use std::{env, path::PathBuf}; -use clap::{command, error::ErrorKind, CommandFactory, Parser, ArgAction}; +use clap::{command, error::ErrorKind, ArgAction, CommandFactory, Parser}; use regex::Regex; use once_cell::sync::Lazy; @@ -31,7 +31,7 @@ pub struct CliArgs { #[arg(short='i', long="init", default_value=None)] pub initfile_path: Option, - #[arg(long="arch", default_value="amd64")] + #[arg(long = "arch", default_value = "amd64")] pub architecture: String, #[arg(short='d', long="debug", action=ArgAction::SetTrue)] diff --git a/src/fs-gen/src/image_builder.rs b/src/fs-gen/src/image_builder.rs index b34221a..fa8803a 100644 --- a/src/fs-gen/src/image_builder.rs +++ b/src/fs-gen/src/image_builder.rs @@ -136,7 +136,7 @@ pub fn merge_layer(blob_paths: &[PathBuf], output_folder: &Path, tmp_folder: &Pa .with_context(|| "Failed to unmount the fuse session".to_string())?; let _ = handle.join(); - + info!("Finished merging layers!"); Ok(()) } diff --git a/src/fs-gen/src/initramfs_generator.rs b/src/fs-gen/src/initramfs_generator.rs index f9c5d40..c216fa0 100644 --- a/src/fs-gen/src/initramfs_generator.rs +++ b/src/fs-gen/src/initramfs_generator.rs @@ -1,10 +1,10 @@ -use std::fs::{File, Permissions, copy as fscopy}; -use std::io::{Write, copy as iocopy}; +use anyhow::{Context, Result}; +use std::fs::{copy as fscopy, File, Permissions}; +use std::io::{copy as iocopy, Write}; use std::os::unix::fs::PermissionsExt; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; use tracing::info; -use anyhow::{Context, Result}; const INIT_FILE: &str = include_str!("../resources/initfile"); @@ -39,8 +39,8 @@ pub fn insert_agent(destination: &Path, agent_path: PathBuf) -> Result<()> { file.set_permissions(Permissions::from_mode(0o755)) .with_context(|| "Failed to set permissions for agent file".to_string())?; - let mut agent = File::open(agent_path) - .with_context(|| "Could not open host agent file".to_string())?; + let mut agent = + File::open(agent_path).with_context(|| "Could not open host agent file".to_string())?; iocopy(&mut agent, &mut file) .with_context(|| "Failed to copy agent contents from host to destination".to_string())?; @@ -65,9 +65,9 @@ pub fn generate_initramfs(root_directory: &Path, output: &Path) -> Result<()> { .spawn() .with_context(|| "Failed to package initramfs into bundle".to_string())?; - command - .wait() - .with_context(|| "Encountered exception while waiting for bundling to finish".to_string())?; + command.wait().with_context(|| { + "Encountered exception while waiting for bundling to finish".to_string() + })?; info!("Initramfs generated!"); diff --git a/src/fs-gen/src/loader/download.rs b/src/fs-gen/src/loader/download.rs index bfa3e38..1cc8c65 100644 --- a/src/fs-gen/src/loader/download.rs +++ b/src/fs-gen/src/loader/download.rs @@ -1,11 +1,11 @@ +use crate::loader::errors::ImageLoaderError; +use crate::loader::utils::{get_docker_download_token, unpack_tarball}; +use anyhow::{Context, Result}; use reqwest::blocking::Client; +use serde_json::Value; use std::fs::create_dir_all; use std::path::{Path, PathBuf}; use tracing::{debug, info, warn}; -use anyhow::{Context, Result}; -use serde_json::Value; -use crate::loader::errors::ImageLoaderError; -use crate::loader::utils::{get_docker_download_token, unpack_tarball}; pub(crate) fn download_image_fs( image_name: &str, @@ -17,7 +17,11 @@ pub(crate) fn download_image_fs( // Get image's name and tag let image_and_tag: Vec<&str> = image_name.split(':').collect(); let image_name = image_and_tag[0]; - let tag = if image_and_tag.len() < 2 { "latest" } else { image_and_tag[1] }; + let tag = if image_and_tag.len() < 2 { + "latest" + } else { + image_and_tag[1] + }; // Get download token and download manifest let client = Client::new(); @@ -25,7 +29,6 @@ pub(crate) fn download_image_fs( let manifest = download_manifest(&client, token, image_name, tag) .map_err(|e| ImageLoaderError::Error { source: e })?; - if let Some(layers) = manifest["layers"].as_array() { // We have layers already, no need to look into sub-manifests. info!("Found layers in manifest"); @@ -33,14 +36,10 @@ pub(crate) fn download_image_fs( architecture, "Manifest did not specify architecture, the initramfs may not work for the requested architecture" ); - create_dir_all(&output_file).with_context(|| "Could not create output directory for image downloading")?; - return download_layers( - layers, - &client, - token, - image_name, - &output_file - ).map_err(|e| ImageLoaderError::Error { source: e }) + create_dir_all(&output_file) + .with_context(|| "Could not create output directory for image downloading")?; + return download_layers(layers, &client, token, image_name, &output_file) + .map_err(|e| ImageLoaderError::Error { source: e }); } // Below, we assume there are no layers found. @@ -48,10 +47,16 @@ pub(crate) fn download_image_fs( let manifest_list = match manifest["manifests"].as_array() { // No sub-manifests found, we throw an error. - None => Err(ImageLoaderError::ManifestNotFound(image_name.to_string(), tag.to_string()))?, - Some(m) => m + None => Err(ImageLoaderError::ManifestNotFound( + image_name.to_string(), + tag.to_string(), + ))?, + Some(m) => m, }; - info!(architecture, "Manifest list found. Looking for an architecture-specific manifest..."); + info!( + architecture, + "Manifest list found. Looking for an architecture-specific manifest..." + ); let arch_specific_manifest = manifest_list.iter().find(|manifest| { manifest["platform"].as_object().unwrap()["architecture"] @@ -61,35 +66,34 @@ pub(crate) fn download_image_fs( }); let submanifest = match arch_specific_manifest { - None => Err(ImageLoaderError::UnsupportedArchitecture(architecture.to_string()))?, + None => Err(ImageLoaderError::UnsupportedArchitecture( + architecture.to_string(), + ))?, Some(m) => { debug!("Downloading architecture-specific manifest"); - download_manifest( - &client, - token, - image_name, - m["digest"].as_str().unwrap() - ).map_err(|e| ImageLoaderError::Error { source: e })? + download_manifest(&client, token, image_name, m["digest"].as_str().unwrap()) + .map_err(|e| ImageLoaderError::Error { source: e })? } }; - + match submanifest["layers"].as_array() { None => Err(ImageLoaderError::LayersNotFound)?, Some(layers) => { - create_dir_all(&output_file).with_context(|| "Could not create output directory for image downloading")?; - download_layers( - layers, - &client, - token, - image_name, - &output_file - ).map_err(|e| ImageLoaderError::Error { source: e }) + create_dir_all(&output_file) + .with_context(|| "Could not create output directory for image downloading")?; + download_layers(layers, &client, token, image_name, &output_file) + .map_err(|e| ImageLoaderError::Error { source: e }) } } } -fn download_manifest(client: &Client, token: &str, image_name: &str, digest: &str) -> Result { +fn download_manifest( + client: &Client, + token: &str, + image_name: &str, + digest: &str, +) -> Result { // Query Docker Hub API to get the image manifest let manifest_url = format!( "https://registry-1.docker.io/v2/library/{}/manifests/{}", @@ -108,8 +112,10 @@ fn download_manifest(client: &Client, token: &str, image_name: &str, digest: &st ) .header("Accept", "application/vnd.oci.image.manifest.v1+json") .bearer_auth(token) - .send().with_context(|| "Could not send request to get manifest data".to_string())? - .json().with_context(|| "Failed to parse manifest to JSON".to_string())?; + .send() + .with_context(|| "Could not send request to get manifest data".to_string())? + .json() + .with_context(|| "Failed to parse manifest to JSON".to_string())?; debug!( manifest = ?manifest, @@ -132,15 +138,19 @@ fn download_layers( // Download and unpack each layer for layer in layers { - let digest = layer["digest"].as_str() + let digest = layer["digest"] + .as_str() .with_context(|| "Failed to get digest for layer".to_string())?; let layer_url = format!( "https://registry-1.docker.io/v2/library/{}/blobs/{}", image_name, digest ); - let response = client.get(&layer_url).bearer_auth(token) - .send().with_context(|| format!("Could not send request for layer digest '{digest}'"))?; + let response = client + .get(&layer_url) + .bearer_auth(token) + .send() + .with_context(|| format!("Could not send request for layer digest '{digest}'"))?; debug!("starting to decode layer with digest '{}'", digest); diff --git a/src/fs-gen/src/loader/errors.rs b/src/fs-gen/src/loader/errors.rs index b6fda91..d262c04 100644 --- a/src/fs-gen/src/loader/errors.rs +++ b/src/fs-gen/src/loader/errors.rs @@ -17,9 +17,7 @@ pub(crate) enum ImageLoaderError { /// Encountered an error during the flow. #[error("Image loading error: {}", .source)] - Error { - source: anyhow::Error - } + Error { source: anyhow::Error }, } impl From for ImageLoaderError { diff --git a/src/fs-gen/src/loader/mod.rs b/src/fs-gen/src/loader/mod.rs index 8f2745d..f79903f 100644 --- a/src/fs-gen/src/loader/mod.rs +++ b/src/fs-gen/src/loader/mod.rs @@ -1,3 +1,3 @@ pub(crate) mod download; pub(crate) mod errors; - mod utils; +mod utils; diff --git a/src/fs-gen/src/loader/utils.rs b/src/fs-gen/src/loader/utils.rs index 64afb73..d65d247 100644 --- a/src/fs-gen/src/loader/utils.rs +++ b/src/fs-gen/src/loader/utils.rs @@ -1,12 +1,13 @@ +use anyhow::{Context, Result}; use flate2::read::GzDecoder; use reqwest::blocking::{Client, Response}; -use std::path::{Path}; +use std::path::Path; use tar::Archive; -use anyhow::{Context, Result}; /// Unpack the tarball to a given directory. pub(super) fn unpack_tarball(response: Response, output_dir: &Path) -> Result<()> { - Archive::new(GzDecoder::new(response)).unpack(output_dir) + Archive::new(GzDecoder::new(response)) + .unpack(output_dir) .with_context(|| format!("Failed to unpack tarball to {}", output_dir.display()))?; Ok(()) } @@ -18,8 +19,11 @@ pub(super) fn get_docker_download_token(client: &Client, image_name: &str) -> Re .send().with_context(|| "Could not send request for anonymous authentication".to_string())? .json().with_context(|| "Failed to parse JSON response for anonymous authentication".to_string())?; - match token_json["token"].as_str().with_context(|| "Failed to get token from anon auth response".to_string()) { + match token_json["token"] + .as_str() + .with_context(|| "Failed to get token from anon auth response".to_string()) + { Ok(t) => Ok(t.to_owned()), - Err(e) => Err(e) + Err(e) => Err(e), } } diff --git a/src/fs-gen/src/main.rs b/src/fs-gen/src/main.rs index 07ede5f..045e1c0 100644 --- a/src/fs-gen/src/main.rs +++ b/src/fs-gen/src/main.rs @@ -1,12 +1,12 @@ +use anyhow::{bail, Context, Result}; use std::{fs::remove_dir_all, path::Path}; -use tracing::{debug, error, info}; -use anyhow::{Result, bail, Context}; use tracing::level_filters::LevelFilter; +use tracing::{debug, error, info}; use tracing_subscriber::filter::EnvFilter; use crate::cli_args::CliArgs; -use crate::initramfs_generator::{create_init_file, generate_initramfs, insert_agent}; use crate::image_builder::merge_layer; +use crate::initramfs_generator::{create_init_file, generate_initramfs, insert_agent}; use crate::loader::download::download_image_fs; mod cli_args; @@ -14,18 +14,17 @@ mod image_builder; mod initramfs_generator; mod loader; -fn run( - args: CliArgs, -) -> Result<()> { +fn run(args: CliArgs) -> Result<()> { let layers_subdir = args.temp_directory.join("layers/"); let overlay_subdir = args.temp_directory.join("overlay/"); let _binding = args.temp_directory.join("output/"); let output_subdir = _binding.as_path(); // image downloading and unpacking - let layers_paths = match download_image_fs(&args.image_name, &args.architecture, layers_subdir) { + let layers_paths = match download_image_fs(&args.image_name, &args.architecture, layers_subdir) + { Err(e) => bail!(e), - Ok(e) => e + Ok(e) => e, }; debug!("Layers' paths: {:?}", layers_paths); @@ -51,18 +50,27 @@ fn main() -> Result<()> { .with_env_filter( EnvFilter::builder() .with_default_directive( - (if args.debug { LevelFilter::DEBUG } else { LevelFilter::INFO }).into() + (if args.debug { + LevelFilter::DEBUG + } else { + LevelFilter::INFO + }) + .into(), ) .from_env()? - .add_directive("fuse_backend_rs=warn".parse()?) + .add_directive("fuse_backend_rs=warn".parse()?), ) .init(); - + // tracing_subscriber::fmt() // .with_max_level(if args.debug { Level::DEBUG } else { Level::INFO }) // .init(); - info!("Cloudlet initramfs generator: '{}' v{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")); + info!( + "Cloudlet initramfs generator: '{}' v{}", + env!("CARGO_PKG_NAME"), + env!("CARGO_PKG_VERSION") + ); info!("Generating for image '{}'", args.image_name); debug!(