a3s-box-runtime 3.2.3

MicroVM runtime engine — VM lifecycle, OCI images, attestation, networking
Documentation
use std::sync::Arc;

use a3s_box_core::OperationId;

use super::*;
use crate::oci::build::engine::BuildExecutionObserver;
use crate::OCI_IMAGE_MANIFEST_MEDIA_TYPE;

#[tokio::test]
async fn execution_returns_a_plan_bound_typed_oci_output() {
    let temporary = tempfile::TempDir::new().unwrap();
    let source = temporary.path().join("source");
    let store_root = temporary.path().join("images");
    std::fs::create_dir_all(&source).unwrap();
    std::fs::write(
        source.join("Dockerfile"),
        "FROM scratch\nCOPY value /value\n",
    )
    .unwrap();
    std::fs::write(source.join("value"), "typed-output\n").unwrap();

    let platform = if cfg!(target_arch = "aarch64") {
        "linux/arm64"
    } else {
        "linux/amd64"
    };
    let plan = BoxBuildPlan::parse_acl(&format!(
        r#"
build "oci" {{
  cache = "disabled"
  context = "."
  file = "Dockerfile"
  network = "none"
  platform = "{platform}"
  schema = "a3s.box.build-plan.v1"
}}
"#
    ))
    .unwrap();
    let expected_plan_digest = plan.canonical_digest().unwrap();
    let store = Arc::new(ImageStore::new(&store_root, 64 * 1024 * 1024).unwrap());

    let result = execute_build_plan(
        &plan,
        &source,
        BoxBuildOptions {
            tag: Some("a3s-cloud/build:test".into()),
            quiet: true,
        },
        Arc::clone(&store),
    )
    .await
    .unwrap();

    assert_eq!(result.plan_digest, expected_plan_digest);
    assert_eq!(result.output.reference, "a3s-cloud/build:test");
    assert_eq!(result.output.platform, *plan.platform());
    assert_eq!(
        result.output.descriptor.media_type,
        OCI_IMAGE_MANIFEST_MEDIA_TYPE
    );
    assert_eq!(result.output.descriptor.digest, result.output.digest);
    assert!(result.output.descriptor.size > 0);
    assert_eq!(result.output.layer_count, 1);
    assert_eq!(result.output.blob_count, 3);
    assert!(result.output.content_bytes() >= result.output.descriptor.size);
    assert!(result
        .output
        .layout_directory
        .starts_with(store_root.canonicalize().unwrap()));
    assert!(result.output.layout_directory.join("oci-layout").is_file());
    assert!(result.output.layout_directory.join("index.json").is_file());
    crate::oci::OciImage::from_path(&result.output.layout_directory).unwrap();

    let stored = store.get("a3s-cloud/build:test").await.unwrap();
    assert_eq!(stored.digest, result.output.descriptor.digest);
    assert_eq!(
        stored.path.canonicalize().unwrap(),
        result.output.layout_directory
    );
    assert_eq!(stored.size_bytes, result.output.content_bytes());
}

#[tokio::test]
async fn image_commit_permit_serializes_cancellation_on_the_operation_journal() {
    let temporary = tempfile::TempDir::new().unwrap();
    let store_root = temporary.path().join("images");
    let identity = BuildOperationIdentity::new(
        OperationId::new("cloud-build-commit-permit").unwrap(),
        format!("sha256:{}", "a".repeat(64)),
    )
    .unwrap();
    let plan = BoxBuildPlan::parse_acl(&format!(
        r#"
build "oci" {{
  cache = "disabled"
  context = "."
  file = "Dockerfile"
  network = "none"
  platform = "linux/{}"
  schema = "a3s.box.build-plan.v1"
}}
"#,
        if cfg!(target_arch = "aarch64") {
            "arm64"
        } else {
            "amd64"
        }
    ))
    .unwrap();
    let plan_digest = plan.canonical_digest().unwrap();
    let store = Arc::new(ImageStore::new(&store_root, 64 * 1024 * 1024).unwrap());
    let journal = BuildOperationJournal::for_image_store(&store, identity.operation_id())
        .await
        .unwrap();
    let locked = journal.lock(identity.operation_id()).await.unwrap();
    locked
        .write_supervised(
            SupervisedBuildOperation::new(&identity, plan_digest.clone(), plan.cache()).unwrap(),
        )
        .await
        .unwrap();
    drop(locked);

    let observer = JournalBuildObserver {
        journal,
        identity: identity.clone(),
        plan_digest,
        cache_policy: plan.cache(),
    };
    let permit = observer.acquire_image_commit_permit().await.unwrap();
    let cancellation_identity = identity.clone();
    let cancellation_plan = plan.clone();
    let cancellation_store = Arc::clone(&store);
    let mut cancellation = tokio::spawn(async move {
        cancel_recorded_build_plan(
            &cancellation_identity,
            &cancellation_plan,
            &cancellation_store,
        )
        .await
    });

    assert!(
        tokio::time::timeout(std::time::Duration::from_millis(100), &mut cancellation)
            .await
            .is_err(),
        "cancellation must wait for the ImageStore commit permit"
    );
    drop(permit);

    assert_eq!(
        tokio::time::timeout(std::time::Duration::from_secs(2), cancellation)
            .await
            .expect("cancellation must resume after commit permit release")
            .expect("cancellation task must not panic")
            .unwrap(),
        BuildCancellationOutcome::Requested
    );
}