monocore 0.2.1

`monocore` is a secure MicroVM provisioning system for running untrusted code in isolated environments.
Documentation
//! This example demonstrates making HTTP requests from inside a microvm using curl with:
//! - 1 virtual CPU
//! - 1024 MiB of RAM
//! - Configurable network restrictions
//! - Default target of example.com (93.184.216.34:80)
//!
//! To run the example with default settings (non-local mode):
//! ```bash
//! make example microvm_curl
//! ```
//!
//! To run with local-only network restrictions:
//! ```bash
//! make example microvm_curl -- --local-only
//! # or
//! make example microvm_curl -- -l
//! ```
//!
//! To specify a different target:
//! ```bash
//! make example microvm_curl -- localhost:8080
//! ```
//!
//! You can combine both options:
//! ```bash
//! make example microvm_curl -- --local-only localhost:8080
//! ```

use anyhow::{Context, Result};
use clap::Parser;
use monocore::{utils, vm::MicroVm};

//--------------------------------------------------------------------------------------------------
// Types
//--------------------------------------------------------------------------------------------------

#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Args {
    /// Target URL or IP:port to curl
    #[arg(default_value = "93.184.216.34:80")] // -> example.com
    target: String,

    /// Whether to restrict to local connections only
    #[arg(long, short, default_value_t = false)]
    local_only: bool,
}

//--------------------------------------------------------------------------------------------------
// Functions: main
//--------------------------------------------------------------------------------------------------

#[tokio::main]
async fn main() -> Result<()> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::DEBUG)
        .init();

    // Parse command line arguments
    let args = Args::parse();

    // Use specific directories for OCI and rootfs
    let build_dir = format!("{}/build", env!("CARGO_MANIFEST_DIR"));
    let oci_dir = format!("{}/oci", build_dir);

    // Parse image reference
    let image_ref = "library/fedora:latest";
    let (_, _, rootfs_name) = utils::parse_image_ref(image_ref).unwrap();
    let rootfs_dir = format!("{}/rootfs/reference/{}", build_dir, rootfs_name);

    // Pull and merge Fedora image
    utils::pull_docker_image(&oci_dir, image_ref).await?;
    utils::merge_image_layers(&oci_dir, &rootfs_dir, image_ref).await?;

    // Build the MicroVm
    let vm = MicroVm::builder()
        .root_path(format!("{}/merged", rootfs_dir))
        .num_vcpus(1)
        .exec_path("/bin/curl")
        .args([args.target.as_str()])
        .local_only(args.local_only)
        .ram_mib(1024)
        .build()
        .context("Failed to build MicroVm")?;

    // Start the MicroVm
    tracing::info!("Starting MicroVm...");
    vm.start()?;

    Ok(())
}