armada_client/lib.rs
1//! Rust client for the [Armada](https://armadaproject.io) batch-job scheduler.
2//!
3//! This crate provides an async gRPC client for submitting and monitoring batch
4//! jobs on an Armada cluster. It is built on top of [tonic] and exposes a
5//! small, ergonomic API that can be shared across async tasks without locking.
6//!
7//! # Quick start
8//!
9//! ```no_run
10//! use armada_client::k8s::io::api::core::v1::{Container, PodSpec};
11//! use armada_client::{
12//! ArmadaClient, JobRequestItemBuilder, JobSubmitRequest, StaticTokenProvider,
13//! };
14//!
15//! #[tokio::main]
16//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
17//! // 1. Connect (plaintext). Use `connect_tls` for production clusters.
18//! let client = ArmadaClient::connect(
19//! "http://localhost:50051",
20//! StaticTokenProvider::new("my-token"),
21//! )
22//! .await?;
23//!
24//! // 2. Build a job item — pod spec required before `.build()` compiles.
25//! let pod_spec = PodSpec {
26//! containers: vec![Container {
27//! name: Some("main".into()),
28//! image: Some("busybox:latest".into()),
29//! command: vec!["echo".into()],
30//! args: vec!["hello".into()],
31//! ..Default::default()
32//! }],
33//! ..Default::default()
34//! };
35//!
36//! let item = JobRequestItemBuilder::new()
37//! .namespace("default")
38//! .priority(1.0)
39//! .pod_spec(pod_spec)
40//! .build();
41//!
42//! // 3. Submit.
43//! let response = client
44//! .submit(JobSubmitRequest {
45//! queue: "my-queue".into(),
46//! job_set_id: "my-job-set".into(),
47//! job_request_items: vec![item],
48//! })
49//! .await?;
50//!
51//! for r in &response.job_response_items {
52//! println!("job_id={}", r.job_id);
53//! }
54//! Ok(())
55//! }
56//! ```
57//!
58//! # Features
59//!
60//! | Feature | How to use |
61//! |---|---|
62//! | Plaintext connection | [`ArmadaClient::connect`] |
63//! | TLS connection (system roots) | [`ArmadaClient::connect_tls`] |
64//! | Per-call timeout | [`ArmadaClient::with_timeout`] |
65//! | Job submission | [`ArmadaClient::submit`] |
66//! | Cancel jobs by ID | [`ArmadaClient::cancel_jobs`] |
67//! | Cancel a job set | [`ArmadaClient::cancel_job_set`] |
68//! | Event streaming | [`ArmadaClient::watch`] |
69//! | Static bearer token | [`StaticTokenProvider`] |
70//! | Custom auth (OIDC, OAuth2…) | Implement [`TokenProvider`] |
71//! | Compile-time safe job builder | [`JobRequestItemBuilder`] |
72//!
73//! # Kubernetes proto types
74//!
75//! Armada job specs embed Kubernetes `PodSpec` and related types. These are
76//! generated from the upstream k8s protobufs and re-exported under the
77//! [`k8s`] module, mirroring the proto package hierarchy:
78//!
79//! ```ignore
80//! use armada_client::k8s::io::api::core::v1::{Container, PodSpec, ResourceRequirements};
81//! use armada_client::k8s::io::apimachinery::pkg::api::resource::Quantity;
82//! ```
83//!
84//! # Cloning and concurrent use
85//!
86//! [`ArmadaClient`] is `Clone`. All clones share the same underlying
87//! connection pool — cloning is cheap and the correct way to use the client
88//! across multiple tasks:
89//!
90//! ```no_run
91//! # use armada_client::{ArmadaClient, StaticTokenProvider};
92//! # async fn example() -> Result<(), armada_client::Error> {
93//! let client = ArmadaClient::connect("http://localhost:50051", StaticTokenProvider::new("tok"))
94//! .await?;
95//!
96//! let c1 = client.clone();
97//! let c2 = client.clone();
98//! tokio::join!(
99//! async move { /* use c1 */ },
100//! async move { /* use c2 */ },
101//! );
102//! # Ok(())
103//! # }
104//! ```
105
106pub mod api {
107 #![allow(
108 clippy::tabs_in_doc_comments,
109 clippy::doc_lazy_continuation,
110 clippy::doc_overindented_list_items,
111 clippy::large_enum_variant
112 )]
113 tonic::include_proto!("api");
114}
115
116// google.api types (HttpRule etc.) generated as a side-effect of compiling the
117// Armada API protos. Not part of the public API — used internally by api.rs.
118pub(crate) mod google {
119 pub mod api {
120 #![allow(
121 dead_code,
122 clippy::tabs_in_doc_comments,
123 clippy::doc_lazy_continuation,
124 clippy::doc_overindented_list_items,
125 clippy::large_enum_variant
126 )]
127 tonic::include_proto!("google.api");
128 }
129}
130
131// k8s types referenced by the api package — must mirror the proto package hierarchy
132// so that generated api.rs cross-package refs (e.g., super::k8s::io::api::core::v1::PodSpec) resolve.
133pub mod k8s {
134 #![allow(
135 clippy::tabs_in_doc_comments,
136 clippy::doc_lazy_continuation,
137 clippy::doc_overindented_list_items,
138 clippy::large_enum_variant
139 )]
140 pub mod io {
141 pub mod api {
142 pub mod core {
143 pub mod v1 {
144 tonic::include_proto!("k8s.io.api.core.v1");
145 }
146 }
147 pub mod networking {
148 pub mod v1 {
149 tonic::include_proto!("k8s.io.api.networking.v1");
150 }
151 }
152 }
153 pub mod apimachinery {
154 pub mod pkg {
155 pub mod api {
156 pub mod resource {
157 tonic::include_proto!("k8s.io.apimachinery.pkg.api.resource");
158 }
159 }
160 pub mod apis {
161 pub mod meta {
162 pub mod v1 {
163 tonic::include_proto!("k8s.io.apimachinery.pkg.apis.meta.v1");
164 }
165 }
166 }
167 pub mod runtime {
168 tonic::include_proto!("k8s.io.apimachinery.pkg.runtime");
169 }
170 pub mod util {
171 pub mod intstr {
172 tonic::include_proto!("k8s.io.apimachinery.pkg.util.intstr");
173 }
174 }
175 }
176 }
177 }
178}
179
180pub mod auth;
181pub mod builder;
182pub mod client;
183pub mod error;
184
185// Convenience re-exports for the public API surface
186pub use api::{
187 CancellationResult, EventMessage, EventStreamMessage, JobCancelRequest, JobSetCancelRequest,
188 JobSetFilter, JobState, JobSubmitRequest, JobSubmitRequestItem, JobSubmitResponse,
189};
190pub use auth::{BasicAuthProvider, StaticTokenProvider, TokenProvider};
191pub use builder::JobRequestItemBuilder;
192pub use client::ArmadaClient;
193pub use error::Error;
194pub use futures::stream::BoxStream;