Skip to content

Commit

Permalink
chore: cargo fmt
Browse files Browse the repository at this point in the history
Signed-off-by: BioTheWolff <[email protected]>
  • Loading branch information
BioTheWolff committed Apr 26, 2024
1 parent e416b71 commit 5b3ffbb
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 71 deletions.
4 changes: 2 additions & 2 deletions src/fs-gen/src/cli_args.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -31,7 +31,7 @@ pub struct CliArgs {
#[arg(short='i', long="init", default_value=None)]
pub initfile_path: Option<PathBuf>,

#[arg(long="arch", default_value="amd64")]
#[arg(long = "arch", default_value = "amd64")]
pub architecture: String,

#[arg(short='d', long="debug", action=ArgAction::SetTrue)]
Expand Down
2 changes: 1 addition & 1 deletion src/fs-gen/src/image_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
}
Expand Down
16 changes: 8 additions & 8 deletions src/fs-gen/src/initramfs_generator.rs
Original file line number Diff line number Diff line change
@@ -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");

Expand Down Expand Up @@ -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())?;

Expand All @@ -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!");

Expand Down
88 changes: 49 additions & 39 deletions src/fs-gen/src/loader/download.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -17,41 +17,46 @@ 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();
let token = &get_docker_download_token(&client, image_name)?;
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");
warn!(
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.
// We dig into sub-manifests to try and find a suitable one to download, with hopefully layers inside.

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"]
Expand All @@ -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<Value> {
fn download_manifest(
client: &Client,
token: &str,
image_name: &str,
digest: &str,
) -> Result<Value> {
// Query Docker Hub API to get the image manifest
let manifest_url = format!(
"https://registry-1.docker.io/v2/library/{}/manifests/{}",
Expand All @@ -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,
Expand All @@ -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);

Expand Down
4 changes: 1 addition & 3 deletions src/fs-gen/src/loader/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<anyhow::Error> for ImageLoaderError {
Expand Down
2 changes: 1 addition & 1 deletion src/fs-gen/src/loader/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub(crate) mod download;
pub(crate) mod errors;
mod utils;
mod utils;
14 changes: 9 additions & 5 deletions src/fs-gen/src/loader/utils.rs
Original file line number Diff line number Diff line change
@@ -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(())
}
Expand All @@ -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),
}
}
32 changes: 20 additions & 12 deletions src/fs-gen/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,31 +1,30 @@
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;
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);

Expand All @@ -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!(
Expand Down

0 comments on commit 5b3ffbb

Please sign in to comment.