1#![cfg_attr(feature = "docs", doc = include_str!("../README.md"))]
18#![allow(clippy::derive_partial_eq_without_eq)]
21
22pub use tonic;
23
24pub mod types {
26 tonic::include_proto!("containerd.types");
27
28 pub mod v1 {
29 tonic::include_proto!("containerd.v1.types");
30 }
31 pub mod transfer {
32 tonic::include_proto!("containerd.types.transfer");
33 }
34}
35
36pub mod google {
38 #[allow(rustdoc::broken_intra_doc_links)]
39 pub mod rpc {
40 tonic::include_proto!("google.rpc");
41 }
42}
43
44pub mod services {
46 #[allow(clippy::tabs_in_doc_comments)]
47 #[allow(rustdoc::invalid_rust_codeblocks)]
48 #[allow(rustdoc::invalid_html_tags)]
49 pub mod v1 {
50 tonic::include_proto!("containerd.services.containers.v1");
51 tonic::include_proto!("containerd.services.content.v1");
52 tonic::include_proto!("containerd.services.diff.v1");
53 tonic::include_proto!("containerd.services.events.v1");
54 tonic::include_proto!("containerd.services.images.v1");
55 tonic::include_proto!("containerd.services.introspection.v1");
56 tonic::include_proto!("containerd.services.leases.v1");
57 tonic::include_proto!("containerd.services.namespaces.v1");
58 tonic::include_proto!("containerd.services.streaming.v1");
59 tonic::include_proto!("containerd.services.tasks.v1");
60 tonic::include_proto!("containerd.services.transfer.v1");
61
62 pub mod sandbox {
65 tonic::include_proto!("containerd.services.sandbox.v1");
66 }
67
68 pub mod snapshots {
70 tonic::include_proto!("containerd.services.snapshots.v1");
71 }
72
73 tonic::include_proto!("containerd.services.version.v1");
74 }
75}
76
77pub mod events {
79 tonic::include_proto!("containerd.events");
80}
81
82#[cfg(feature = "connect")]
86pub async fn connect(
87 path: impl AsRef<std::path::Path>,
88) -> Result<tonic::transport::Channel, tonic::transport::Error> {
89 use tonic::transport::Endpoint;
90
91 let path = path.as_ref().to_path_buf();
92
93 let channel = Endpoint::try_from("http://[::]")?
97 .connect_with_connector(tower::service_fn(move |_| {
98 let path = path.clone();
99
100 async move {
101 #[cfg(unix)]
102 {
103 Ok::<_, std::io::Error>(hyper_util::rt::TokioIo::new(
104 tokio::net::UnixStream::connect(path).await?,
105 ))
106 }
107
108 #[cfg(windows)]
109 {
110 let client = tokio::net::windows::named_pipe::ClientOptions::new()
111 .open(&path)
112 .map_err(|e| std::io::Error::from(e))?;
113
114 Ok::<_, std::io::Error>(hyper_util::rt::TokioIo::new(client))
115 }
116 }
117 }))
118 .await?;
119
120 Ok(channel)
121}
122
123use prost::{Message, Name};
124use prost_types::Any;
125
126pub fn to_any<T: Message + Name>(m: &T) -> Any {
131 let mut anyt = Any::from_msg(m).unwrap();
132 anyt.type_url = T::full_name();
133 anyt
134}
135
136#[macro_export]
140macro_rules! with_namespace {
141 ($req:expr, $ns:expr) => {{
142 let mut req = Request::new($req);
143 let md = req.metadata_mut();
144 md.insert("containerd-namespace", $ns.parse().unwrap());
146 req
147 }};
148}
149
150use services::v1::{
151 containers_client::ContainersClient,
152 content_client::ContentClient,
153 diff_client::DiffClient,
154 events_client::EventsClient,
155 images_client::ImagesClient,
156 introspection_client::IntrospectionClient,
157 leases_client::LeasesClient,
158 namespaces_client::NamespacesClient,
159 sandbox::{controller_client::ControllerClient, store_client::StoreClient},
160 snapshots::snapshots_client::SnapshotsClient,
161 streaming_client::StreamingClient,
162 tasks_client::TasksClient,
163 transfer_client::TransferClient,
164 version_client::VersionClient,
165};
166use tonic::transport::{Channel, Error};
167
168pub struct Client {
170 channel: Channel,
171}
172
173impl From<Channel> for Client {
174 fn from(value: Channel) -> Self {
175 Self { channel: value }
176 }
177}
178
179impl Client {
180 #[cfg(feature = "connect")]
182 pub async fn from_path(path: impl AsRef<std::path::Path>) -> Result<Self, Error> {
183 let channel = connect(path).await?;
184 Ok(Self { channel })
185 }
186
187 #[inline]
189 pub fn channel(&self) -> Channel {
190 self.channel.clone()
191 }
192
193 #[inline]
195 pub fn version(&self) -> VersionClient<Channel> {
196 VersionClient::new(self.channel())
197 }
198
199 #[inline]
201 pub fn tasks(&self) -> TasksClient<Channel> {
202 TasksClient::new(self.channel())
203 }
204
205 #[inline]
207 pub fn transfer(&self) -> TransferClient<Channel> {
208 TransferClient::new(self.channel())
209 }
210
211 #[inline]
213 pub fn sandbox_store(&self) -> StoreClient<Channel> {
214 StoreClient::new(self.channel())
215 }
216
217 #[inline]
219 pub fn streaming(&self) -> StreamingClient<Channel> {
220 StreamingClient::new(self.channel())
221 }
222
223 #[inline]
225 pub fn sandbox_controller(&self) -> ControllerClient<Channel> {
226 ControllerClient::new(self.channel())
227 }
228
229 #[inline]
231 pub fn snapshots(&self) -> SnapshotsClient<Channel> {
232 SnapshotsClient::new(self.channel())
233 }
234
235 #[inline]
237 pub fn namespaces(&self) -> NamespacesClient<Channel> {
238 NamespacesClient::new(self.channel())
239 }
240
241 #[inline]
243 pub fn leases(&self) -> LeasesClient<Channel> {
244 LeasesClient::new(self.channel())
245 }
246
247 #[inline]
249 pub fn introspection(&self) -> IntrospectionClient<Channel> {
250 IntrospectionClient::new(self.channel())
251 }
252
253 #[inline]
255 pub fn images(&self) -> ImagesClient<Channel> {
256 ImagesClient::new(self.channel())
257 }
258
259 #[inline]
261 pub fn events(&self) -> EventsClient<Channel> {
262 EventsClient::new(self.channel())
263 }
264
265 #[inline]
267 pub fn diff(&self) -> DiffClient<Channel> {
268 DiffClient::new(self.channel())
269 }
270
271 #[inline]
273 pub fn content(&self) -> ContentClient<Channel> {
274 ContentClient::new(self.channel())
275 }
276
277 #[inline]
279 pub fn containers(&self) -> ContainersClient<Channel> {
280 ContainersClient::new(self.channel())
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use prost_types::Any;
287
288 use crate::events::ContainerCreate;
289
290 #[test]
291 fn any_roundtrip() {
292 let original = ContainerCreate {
293 id: "test".to_string(),
294 image: "test".to_string(),
295 runtime: None,
296 };
297
298 let any = Any::from_msg(&original).expect("should not fail to encode");
299 let decoded: ContainerCreate = any.to_msg().expect("should not fail to decode");
300
301 assert_eq!(original, decoded)
302 }
303}