Expand description
cargo-athena — compile regular Rust into Argo Workflow YAML.
This facade is the only crate users depend on. It re-exports the
runtime (cargo_athena_core) and the proc macros
(cargo_athena_macros) behind one stable ::cargo_athena path, which is
also the path the generated code targets.
ⓘ
use cargo_athena::{workflow, container}; // `host!` is used path-qualified
#[workflow]
fn run_foo() {
let a = some_other_workflow("asdf".to_string());
run_a_container(a);
}
#[container(image = "ghcr.io/acme/app:latest")]
fn run_a_container(a: String) {
let cfg = cargo_athena::host!("/etc/myapp"); // -> hostPath volume; compile error outside #[container]/#[fragment]
println!("{cfg} {a}");
}
// entrypoint is a *type*; referencing it force-links the closure.
fn main() { cargo_athena::entrypoint!(run_foo); }Modules§
- api
- Argo Workflows API types — a hand-owned, curated subset.
- inventory
- github crates-io docs-rs
- rt
- Runtime shims referenced by the declaration macros. Artifact ports are plain files at fixed paths; Argo moves them (no S3 from us).
- serde_
json - Serde JSON
- serde_
norway - ![github] ![crates-io] ![docs-rs]
Macros§
- entrypoint
- User-facing entrypoint. Captures the calling binary’s identity
(
CARGO_PKG_NAME/CARGO_PKG_VERSION/CARGO_BIN_NAME) at the user binary’s compile time and threads it intoentrypoint_implso the emitted S3 artifact key ({crate}/<tag>/{bin}.tar.gz) matches whatcargo athena publishuploads. Use ascargo_athena::entrypoint!(MyRootWorkflow). - host
host!("/lit/path")— declare a hostPath volume for the enclosing container, evaluating to the (already-mounted) path at runtime.- load_
artifact - Declare an Argo input artifact port and read it (bytes) at
runtime. See the
host!doc for the gate / LSP-stub pattern shared by every decl macro. - load_
artifact_ str - Declare an Argo input artifact port and read it (UTF-8) at runtime.
- pvc
- Mount a PVC of type
T(a unit struct that implementsPvcvia#[ephemeral_pvc]or#[external_pvc]) on this container’s pod, and evaluate to the (already-mounted) path —&'static Path, picked deterministically from the type’sPvc::MOUNT_PATHso emit-side and in-pod always agree. - save_
artifact - Declare an Argo output artifact port and write bytes to it at runtime.
- save_
artifact_ str - Declare an Argo output artifact port and write a string at runtime.
- secret
- Declare a K8s Secret-sourced env var and read it back at runtime as
a
String. Two literal args:(secret_name, key). Panics at runtime if the env var the macro plants isn’t set; pair withsecret_opt!for the no-panic variant. - secret_
opt - Same as
secret!but returnsOption<String>and emitsoptional: trueon the ArgosecretKeyRef— Argo skips the env entry instead of failing pod-start when the secret/key is missing.
Structs§
- Artifact
- A DAG-wired S3-backed value. Wrap a
#[container](or#[workflow]) return inArtifact<T>to flow the value via Argo’s native artifact passing (outputs.artifacts.return+arguments.artifacts.from) instead of the inline-parameter path (outputs.parameters.return). Lifts the parameter-size ceiling and is the natural shape for binary/large payloads. A consumer acceptingArtifact<T>reads the same value on the other side; the wire is the user’s serializedT(JSON, tar+gzip’d by Argo on the producer and untarred on the consumer, transparent to user code). - Artifact
Ref - One artifact bound into the container at
path, backed by S3. - Artifact
Repository - Athena
Config athena.toml— required bycargo athenaat emit time. Mirrors the parts of Argo’s S3ArtifactRepositorywe inject, plus bootstrap config.- Bootstrap
- Build
Ctx - Fragment registry snapshot, passed to container
builds. - Collector
- Accumulates the reachable templates (as
WorkflowTemplates) and the run-mode dispatch table whileTemplate::collectwalks the closure. - Container
Delivery - What
container_deliveryproduces for one#[container]template. - Container
RunMeta - Purpose-built introspection of one
#[container], derived from the sameTemplate::build()emituses (so it never drifts), but expressed in the runner’s vocabulary instead of Argo’s. Emitted as JSON by the binary whenCARGO_ATHENA_DESCRIBE=<name>is set; consumed bycargo athena emulateto realize the spec under docker/podman locally, and bycargo athena describe. - Defaults
- Fragment
Reg - A
#[fragment]: a plain helper carryinghost!decls. Stillinventory-based — a container’s real body actually calls its fragments, so the symbol reference exists and DCE is not a concern. - Param
Ref - An input parameter and its stringified Rust type (
""if unknown, e.g. synthetic templates). The position in the enclosingparamsvector is the positional argv slot the parameter occupies in-pod. - Probe
Info - What a cargo-athena binary reports in
CARGO_ATHENA_PROBEmode: a handshake the CLI uses to (a) confirm the executable really is a cargo-athena binary, (b) detect CLI/binary version skew, and (c) learn the default/root template (so the workflow argument is optional). Produced with NOathena.toml(noBuildCtx::collect): works source-free / config-free. - PvcReg
- Inventory-registered PVC spec, submitted by every
#[ephemeral_pvc]and#[external_pvc].BuildCtx::collectloads them all into aargo_name → PvcRegmap so emit-side code can materialize the full PVC spec from just a name string (which is what fragment closures propagate). - S3Ref
- Resolved S3 coordinates for one artifact (creds are supplied
locally, e.g. via AWS env vars -
cargo athena emulateusesobject_store; the in-cluster path uses the k8s Secret refs). - S3Repo
- Secret
Ref
Enums§
- IoKind
- How a single Argo input or output flows: inline as a
parameter(Argo stores it in workflow status, sized like a JSON parameter) or via S3 as anartifact(DAG-wired viaoutputs.artifacts/arguments.artifacts.from). The#[container]and#[workflow]macros derive these per-slot from the function signature: a fn argument or return type ofcargo_athena::Artifact<T>isArtifact, everything else isParameter. Stamped intoTemplate::INPUT_KINDS/Template::OUTPUT_KINDand read at emit-time by the workflow’s per-task wiring (parallel to howTemplate::INPUTSis read for parameter names). - PvcLifecycle
- PVC lifecycle, exposed via
Pvc::LIFECYCLE. - Template
Kind - What kind of Argo template a type produces.
Constants§
- ATHENA_
BIN_ DIR - Where Argo’s executor (init container) extracts the per-arch
binaries from our
.tar.gzinput artifact. We rely on Argo’s built-in tarball auto-extraction (noarchive: none, notarin the main container’s image — seecontainer_delivery). - ATHENA_
DIR - Pod-scoped scratch root, backed by an
emptyDiron every container template so all athena paths are writable regardless of the image (distroless / read-only rootfs) and shared with Argo’s init/wait containers for artifact load/collect. - ATHENA_
DIST_ ARTIFACT - Argo input-artifact name of the binary tarball
emitinjects. - ATHENA_
INPUT_ ARTIFACT_ DIR - Where an
Artifact<T>-typed input lands inside the container, one file per arg, named after the arg. The template declaresinputs.artifacts[].path = "/athena/in/<name>"; the run-side body reads + deserializes from there. - ATHENA_
MOUNTS_ DIR - In-pod root for
host!("/p")mounts — the macro never lets the user pick the in-container path (host!("/")would otherwise overlay the host root over the container fs). Eachhost!lands at<this>/<fnv-hex-of-literal>. - ATHENA_
PROBE_ KIND - Fixed marker in a
ProbeInforesponse (thekindfield). Lets a consumer positively identify a cargo-athena binary and reject stray stdout from a non-athena executable with a clear error, rather than an opaque deserialization failure. - ATHENA_
PROTOCOL - Wire-format version of the binary’s metadata modes (PROBE / LIST /
DESCRIBE / EMIT_JSON). The
cargo athenaCLI checks this on PROBE before trusting the other modes. Bump ONLY on a breaking change to those JSON shapes, NOT on every release, so an older CLI keeps working with a newer binary at the same protocol. Within one release line, aProbeInfostruct mismatch at a matching protocol means the workflow binary’s library and the CLI were built from different cargo-athena versions (a dev path-dependency skew) —BinarySource::probenames that precisely rather than failing an opaque deserialize. - ATHENA_
PVCS_ DIR - In-pod root for
pvc!(Type)mounts. Same shape asATHENA_MOUNTS_DIR: each PVC lands at<this>/<fnv-hex-of-argo- name>, never at a user-chosen path, so two crates declaring the same explicit PVC name can’t accidentally overlay each other’s directories. - ATHENA_
RESULT_ ARTIFACT_ FILE - Where an artifact-output
#[container]body writes its serialized return value (read by the template’soutputs.artifacts.return.path, then tar+gzip’d and uploaded by Argo’s executor). The bootstrap exports this asCARGO_ATHENA_OUTPUTfor artifact-output templates; the run-side body has one write site (CARGO_ATHENA_OUTPUT) and stays kind-agnostic. - ATHENA_
RESULT_ FILE - Where a parameter-output
#[container]body writes its serialized return value (read by the template’soutputs.parameters.return.valueFrom.path). The bootstrap exports this asCARGO_ATHENA_OUTPUTfor parameter-output templates. - CARGO_
ATHENA_ TEMPLATE_ ENV - Env var the in-pod entrypoint reads to pick which container template
to run. Argv (positional, in
INPUTSorder) carries the function’s own parameters. - SCRATCH_
VOLUME - Name of the scratch
emptyDirvolume.
Traits§
- Athena
List - Fan-out:
list.fan_out(|x| template(x, ..))runstemplateonce per element (ArgowithParam); the binding is the aggregatedVec<U>of the per-element returns. This trait exists only so the ghost type-checks the element type, the closure, and the resultingVec<U>; the macro lowers the call to Argo and it never runs. - Pvc
- The cross-crate identity of a PVC, implemented by the unit struct
#[ephemeral_pvc]/#[external_pvc]generates. - Template
- The cross-crate identity of a template, implemented by the unit struct
the
#[workflow]/#[container]macros generate.
Functions§
- artifact_
inputs load_artifact!("key")input ports: Argo pulls the exact S3 objectkeyfrom the configured repo into the pod (raw,archive: none).- artifact_
outputs save_artifact!("key")output ports: Argo pushes the written file to the exact S3 objectkeyin the configured repo (raw,archive: none).- container_
delivery - The arch-resolving bootstrap + the S3 binary artifact for one container
template. Called from macro-generated
Template::build(emit only). - container_
volumes - Every container template’s volumes/mounts: the always-present
emptyDirscratch atATHENA_DIR+ the declared hostPaths. Two hostPath sources: - entrypoint_
impl - The entrypoint a user’s
maincalls, parameterised by the root workflow type. ReferencingEforce-links the entire reachable closure (eachcollectcalls callees’collectdirectly). - host_
mount_ path - In-pod mount path for a
host!("/p")literal. - host_
path_ volumes volumes+volumeMountsfor a set of hostPaths (fromhost!). Each mounts athost_mount_path(/athena/mounts/<munged>), NOT at the host’s own path — safe-by-construction.- is_
container_ run trueif this binary is dispatching a container body (in-pod, started by Argo via the emitted bootstrap);falsefor every other mode (cargo athena emit/ls/describe/submit-emit-JSON).- kebab
<crate>-<fn>argo names: lowercases, swaps_for-, trims leading/trailing-so that idiomatic Rust names likefn _unused_helper()orfn foo_()don’t produce DNS-1123-invalid Argo template names (-foo/foo-, both rejected by k8s). Internal__becomes--and is kept (valid).- pvc_
mount_ path - In-pod mount path for a PVC, keyed on its argo name.
- pvc_
volume_ name - K8s Volume name for a PVC mount.
pvc-(4) + 16 hex = 20 chars, fits DNS-1123. - s3_loc
- Build an Argo S3 location (artifact-repository creds from
athena.toml) for an exact objectkey. - secret_
env_ name - Pod env var name a
secret!/secret_opt!decl gets. Derived deterministically from the K8s(secret_name, key)pair so the emit-side (declares the matchingsecretKeyRefenvFrom) and the run-side (reads viastd::env::var) agree. Uppercased, non- alphanumerics flattened to_, halves separated by__to stay distinguishable. - service_
account - Resolve a container template’s ServiceAccount: the
#[container(service_account=...)]override, else[defaults]. - wrap_
workflow_ template - Wrap one inner Argo
templateas a standaloneWorkflowTemplatewhose resource name == the inner template name == its entrypoint.
Type Aliases§
- Toleration
Tuple (key, operator, value, effect, toleration_seconds)— the lowered shape the macro produces for each toleration entry, threaded throughTemplate::TOLERATIONS_IF_ROOTand intoWorkflowSpec.TolerationsbyCollector::stamp_spec.
Attribute Macros§
- container
#[container]- ephemeral_
pvc - Declare a transient (per-workflow-run) PersistentVolumeClaim type.
Apply to a
pub struct Foo;(unit struct, no fields, no generics); athena emits animpl Pvc for Fooand aWorkflowSpec.volume_claim_templates[]entry on every workflow in the binary, so Argo creates the PVC at run start and deletes it at run end. Mount withpvc!(Foo)inside a#[container]/#[fragment]. - external_
pvc - Declare a reference to a pre-existing PersistentVolumeClaim in
the workflow’s namespace. Apply to a
pub struct Foo;. Mount withpvc!(Foo). The PVC must already exist; athena emits novolume_claim_templatesentry. - fragment
- A plain helper function (not a template) that carries pod-resource
declarations (
host!, artifact ports) across function boundaries into every#[container]that transitively calls it. It runs as ordinary Rust inside the caller’s pod and cannot be called from a#[workflow]. See the#[fragment]section of thecontainerdocs (CONTAINER.md) for the full model. - workflow
#[workflow]