i3status_rs/blocks/
docker.rs

1//! Local docker daemon status
2//!
3//! # Configuration
4//!
5//! Key | Values | Default
6//! ----|--------|--------
7//! `interval` | Update interval, in seconds. | `5`
8//! `format` | A string to customise the output of this block. See below for available placeholders. | `" $icon $running.eng(w:1) "`
9//! `socket_path` | The path to the docker socket. Supports path expansions e.g. `~`. | `"/var/run/docker.sock"`
10//!
11//! Key       | Value                          | Type   | Unit
12//! ----------|--------------------------------|--------|-----
13//! `icon`    | A static icon                  | Icon   | -
14//! `total`   | Total containers on the host   | Number | -
15//! `running` | Containers running on the host | Number | -
16//! `stopped` | Containers stopped on the host | Number | -
17//! `paused`  | Containers paused on the host  | Number | -
18//! `images`  | Total images on the host       | Number | -
19//!
20//! # Example
21//!
22//! ```toml
23//! [[block]]
24//! block = "docker"
25//! interval = 2
26//! format = " $icon $running/$total "
27//! ```
28//!
29//! # Icons Used
30//!
31//! - `docker`
32
33use super::prelude::*;
34
35#[derive(Deserialize, Debug, SmartDefault)]
36#[serde(deny_unknown_fields, default)]
37pub struct Config {
38    #[default(5.into())]
39    pub interval: Seconds,
40    pub format: FormatConfig,
41    #[default("/var/run/docker.sock".into())]
42    pub socket_path: ShellString,
43}
44
45pub async fn run(config: &Config, api: &CommonApi) -> Result<()> {
46    let format = config.format.with_default(" $icon $running.eng(w:1) ")?;
47    let socket_path = config.socket_path.expand()?;
48
49    let client = reqwest::Client::builder()
50        .unix_socket(&*socket_path)
51        .build()
52        .unwrap();
53
54    loop {
55        let status: Status = client
56            .get("http://api/info")
57            .send()
58            .await
59            .error("Failed to get response")?
60            .json()
61            .await
62            .error("Failed to deserialize JSON")?;
63
64        let mut widget = Widget::new().with_format(format.clone());
65        widget.set_values(map! {
66            "icon" => Value::icon("docker"),
67            "total" =>   Value::number(status.total),
68            "running" => Value::number(status.running),
69            "paused" =>  Value::number(status.paused),
70            "stopped" => Value::number(status.stopped),
71            "images" =>  Value::number(status.images),
72        });
73        api.set_widget(widget)?;
74
75        select! {
76            _ = sleep(config.interval.0) => (),
77            _ = api.wait_for_update_request() => (),
78        }
79    }
80}
81
82#[derive(Deserialize, Debug)]
83struct Status {
84    #[serde(rename = "Containers")]
85    total: i64,
86    #[serde(rename = "ContainersRunning")]
87    running: i64,
88    #[serde(rename = "ContainersStopped")]
89    stopped: i64,
90    #[serde(rename = "ContainersPaused")]
91    paused: i64,
92    #[serde(rename = "Images")]
93    images: i64,
94}