a3s-box-runtime 3.1.0

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

use a3s_runtime::contract::{
    ArtifactRef, IsolationLevel, NetworkMode, ResourceLimits, RestartPolicy, RuntimeActionRequest,
    RuntimeApplyRequest, RuntimeExecRequest, RuntimeLogQuery, RuntimeLogStream, RuntimeNetworkSpec,
    RuntimeProcessSpec, RuntimeUnitClass, RuntimeUnitSpec,
};
use a3s_runtime::{RuntimeBaseConformanceCase, RuntimeConformanceCase};

use super::super::{DOCKER_IMAGE_MANIFEST, OCI_IMAGE_MANIFEST};
use super::{require, Result};

const DEFAULT_CPU_MILLIS: u64 = 500;
const DEFAULT_MEMORY_BYTES: u64 = 128 * 1024 * 1024;
const DEFAULT_PIDS: u32 = 64;
const DEFAULT_TASK_TIMEOUT_MS: u64 = 10_000;

#[derive(Debug, Clone)]
pub(super) struct CaseFactory {
    prefix: String,
    artifact: ArtifactRef,
}

#[derive(Debug, Clone, Copy)]
pub(super) struct ResourceShape {
    pub cpu_millis: u64,
    pub memory_bytes: u64,
    pub pids: u32,
    pub execution_timeout_ms: Option<u64>,
}

impl ResourceShape {
    pub const fn service() -> Self {
        Self {
            cpu_millis: DEFAULT_CPU_MILLIS,
            memory_bytes: DEFAULT_MEMORY_BYTES,
            pids: DEFAULT_PIDS,
            execution_timeout_ms: None,
        }
    }

    pub const fn task(timeout_ms: u64) -> Self {
        Self {
            execution_timeout_ms: Some(timeout_ms),
            ..Self::service()
        }
    }
}

impl CaseFactory {
    pub(super) fn from_environment(prefix: String) -> Result<Self> {
        let image = std::env::var("A3S_BOX_RUNTIME_CONFORMANCE_IMAGE").map_err(|_| {
            super::failure(
                "A3S_BOX_RUNTIME_CONFORMANCE_IMAGE must be a digest-pinned image reference",
            )
        })?;
        let (repository, digest_hex) = image.rsplit_once("@sha256:").ok_or_else(|| {
            super::failure(
                "A3S_BOX_RUNTIME_CONFORMANCE_IMAGE must end in @sha256:<64 lowercase hex>",
            )
        })?;
        require(
            !repository.is_empty()
                && digest_hex.len() == 64
                && digest_hex
                    .bytes()
                    .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte)),
            "A3S_BOX_RUNTIME_CONFORMANCE_IMAGE has an invalid sha256 digest",
        )?;
        require(
            !repository.contains("//")
                && !repository.contains('@')
                && !repository.contains('?')
                && !repository.contains('#'),
            "A3S_BOX_RUNTIME_CONFORMANCE_IMAGE is not canonical",
        )?;
        let media_type = std::env::var("A3S_BOX_RUNTIME_CONFORMANCE_MEDIA_TYPE")
            .unwrap_or_else(|_| DOCKER_IMAGE_MANIFEST.to_string());
        require(
            matches!(
                media_type.as_str(),
                OCI_IMAGE_MANIFEST | DOCKER_IMAGE_MANIFEST
            ),
            "A3S_BOX_RUNTIME_CONFORMANCE_MEDIA_TYPE is not a supported image manifest",
        )?;
        let digest = format!("sha256:{digest_hex}");
        let artifact = ArtifactRef {
            uri: format!("oci://{repository}@{digest}"),
            digest,
            media_type,
        };
        artifact.validate().map_err(super::invalid)?;
        Ok(Self { prefix, artifact })
    }

    pub(super) fn base_case(&self) -> RuntimeBaseConformanceCase {
        let task_apply = self.task(
            "base-task-success",
            "printf 'r17-base-task-success\\n'",
            DEFAULT_TASK_TIMEOUT_MS,
        );
        let service_apply = self.service(
            "base-service",
            "printf 'r17-base-service-out\\n'; printf 'r17-base-service-err\\n' >&2; exec sleep 3600",
        );
        let task_failure_apply = self.task(
            "base-task-failure",
            "printf 'r17-base-task-failure\\n' >&2; exit 17",
            DEFAULT_TASK_TIMEOUT_MS,
        );
        let task_timeout_apply = self.task("base-task-timeout", "exec sleep 3600", 500);
        let generation_apply = self.service(
            "base-generation",
            "printf 'r17-base-generation\\n'; exec sleep 3600",
        );
        let mut generation_conflict_apply = generation_apply.clone();
        generation_conflict_apply.request_id = self.request_id("base-generation-conflict");
        generation_conflict_apply
            .spec
            .process
            .environment
            .insert("R17_CONFLICT".into(), "true".into());

        RuntimeBaseConformanceCase {
            lifecycle: RuntimeConformanceCase {
                task_remove: self.action("base-task-remove", &task_apply.spec),
                service_stop: self.action("base-service-stop", &service_apply.spec),
                service_remove: self.action("base-service-remove", &service_apply.spec),
                task_apply,
                service_apply,
            },
            task_failure_remove: self.action("base-task-failure-remove", &task_failure_apply.spec),
            task_timeout_remove: self.action("base-task-timeout-remove", &task_timeout_apply.spec),
            generation_remove: self.action("base-generation-remove", &generation_apply.spec),
            task_failure_apply,
            task_timeout_apply,
            generation_apply,
            generation_conflict_apply,
        }
    }

    pub(super) fn task(&self, label: &str, script: &str, timeout_ms: u64) -> RuntimeApplyRequest {
        self.apply(
            label,
            RuntimeUnitClass::Task,
            script,
            ResourceShape::task(timeout_ms),
            RestartPolicy::Never,
        )
    }

    pub(super) fn service(&self, label: &str, script: &str) -> RuntimeApplyRequest {
        self.apply(
            label,
            RuntimeUnitClass::Service,
            script,
            ResourceShape::service(),
            RestartPolicy::Never,
        )
    }

    pub(super) fn apply(
        &self,
        label: &str,
        class: RuntimeUnitClass,
        script: &str,
        resources: ResourceShape,
        restart: RestartPolicy,
    ) -> RuntimeApplyRequest {
        RuntimeApplyRequest {
            schema: RuntimeApplyRequest::SCHEMA.into(),
            request_id: self.request_id(&format!("{label}-apply")),
            deadline_at_ms: None,
            spec: RuntimeUnitSpec {
                schema: RuntimeUnitSpec::SCHEMA.into(),
                unit_id: self.unit_id(label),
                generation: 1,
                class,
                artifact: self.artifact.clone(),
                process: RuntimeProcessSpec {
                    command: vec!["/bin/sh".into(), "-c".into()],
                    args: vec![script.into()],
                    working_directory: Some("/".into()),
                    environment: BTreeMap::from([("R17_CASE".into(), label.into())]),
                },
                mounts: Vec::new(),
                secrets: Vec::new(),
                network: RuntimeNetworkSpec {
                    mode: NetworkMode::None,
                    ports: Vec::new(),
                },
                resources: ResourceLimits {
                    cpu_millis: resources.cpu_millis,
                    memory_bytes: resources.memory_bytes,
                    pids: resources.pids,
                    ephemeral_storage_bytes: None,
                    execution_timeout_ms: resources.execution_timeout_ms,
                },
                isolation: IsolationLevel::Sandbox,
                health: None,
                restart,
                outputs: Vec::new(),
                semantics_profile_digest: None,
            },
        }
    }

    pub(super) fn action(&self, label: &str, spec: &RuntimeUnitSpec) -> RuntimeActionRequest {
        RuntimeActionRequest {
            schema: RuntimeActionRequest::SCHEMA.into(),
            request_id: self.request_id(label),
            unit_id: spec.unit_id.clone(),
            generation: spec.generation,
            deadline_at_ms: None,
        }
    }

    pub(super) fn exec(
        &self,
        label: &str,
        spec: &RuntimeUnitSpec,
        command: Vec<String>,
        timeout_ms: u64,
    ) -> RuntimeExecRequest {
        RuntimeExecRequest {
            schema: RuntimeExecRequest::SCHEMA.into(),
            request_id: self.request_id(label),
            unit_id: spec.unit_id.clone(),
            generation: spec.generation,
            command,
            timeout_ms,
            deadline_at_ms: None,
        }
    }

    pub(super) fn logs(
        &self,
        spec: &RuntimeUnitSpec,
        cursor: Option<String>,
        limit: u32,
        stream: Option<RuntimeLogStream>,
    ) -> RuntimeLogQuery {
        RuntimeLogQuery {
            schema: RuntimeLogQuery::SCHEMA.into(),
            unit_id: spec.unit_id.clone(),
            generation: spec.generation,
            cursor,
            limit,
            stream,
        }
    }

    pub(super) fn request_id(&self, label: &str) -> String {
        format!("{}-{label}", self.prefix)
    }

    pub(super) fn unit_id(&self, label: &str) -> String {
        format!("{}-{label}", self.prefix)
    }
}