docker_pyo3/
secret.rs

1use std::collections::HashMap;
2
3use crate::Pyo3Docker;
4use docker_api::secret::{SecretCreateOpts, SecretListOpts};
5use docker_api::{Secret, Secrets};
6use pyo3::exceptions;
7use pyo3::prelude::*;
8use pyo3::types::PyDict;
9use pythonize::pythonize;
10
11#[pymodule]
12pub fn secret(_py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
13    m.add_class::<Pyo3Secrets>()?;
14    m.add_class::<Pyo3Secret>()?;
15    Ok(())
16}
17
18/// Interface for managing Docker Swarm secrets collection.
19///
20/// Secrets are sensitive data that can be mounted into containers.
21/// Swarm mode must be enabled for these operations to work.
22#[derive(Debug)]
23#[pyclass(name = "Secrets")]
24pub struct Pyo3Secrets {
25    secrets: Secrets,
26}
27
28/// Represents an individual Docker Swarm secret.
29///
30/// Swarm mode must be enabled for these operations to work.
31#[derive(Debug)]
32#[pyclass(name = "Secret")]
33pub struct Pyo3Secret {
34    secret: Secret,
35}
36
37#[pymethods]
38impl Pyo3Secrets {
39    #[new]
40    pub fn new(docker: Pyo3Docker) -> Self {
41        Pyo3Secrets {
42            secrets: Secrets::new(docker.0),
43        }
44    }
45
46    /// Get a specific secret by ID or name.
47    ///
48    /// Args:
49    ///     id: Secret ID or name
50    ///
51    /// Returns:
52    ///     Secret: Secret instance
53    pub fn get(&self, id: &str) -> Pyo3Secret {
54        Pyo3Secret {
55            secret: self.secrets.get(id),
56        }
57    }
58
59    /// List all secrets in the swarm.
60    ///
61    /// Returns:
62    ///     list[dict]: List of secret information dictionaries
63    ///
64    /// Raises:
65    ///     SystemError: If the operation fails (e.g., swarm not initialized)
66    pub fn list(&self) -> PyResult<Py<PyAny>> {
67        let rv = __secrets_list(&self.secrets, &Default::default());
68
69        match rv {
70            Ok(rv) => Ok(pythonize_this!(rv)),
71            Err(rv) => Err(py_sys_exception!(rv)),
72        }
73    }
74
75    /// Create a new secret in the swarm.
76    ///
77    /// Args:
78    ///     name: Name of the secret
79    ///     data: Secret data (will be base64 encoded automatically)
80    ///     labels: Labels as dict (e.g., {"app": "web"})
81    ///
82    /// Returns:
83    ///     Secret: Created secret instance
84    ///
85    /// Raises:
86    ///     SystemError: If the secret cannot be created
87    #[pyo3(signature = (name, data, labels=None))]
88    pub fn create(
89        &self,
90        name: &str,
91        data: &str,
92        labels: Option<&Bound<'_, PyDict>>,
93    ) -> PyResult<Pyo3Secret> {
94        let mut opts = SecretCreateOpts::new(name, data);
95
96        if let Some(labels_dict) = labels {
97            let labels_map: HashMap<String, String> = labels_dict.extract().unwrap();
98            for (k, v) in labels_map {
99                opts = opts.add_label(k, v);
100            }
101        }
102
103        let rv = __secrets_create(&self.secrets, &opts);
104
105        match rv {
106            Ok(secret) => Ok(Pyo3Secret { secret }),
107            Err(rv) => Err(py_sys_exception!(rv)),
108        }
109    }
110}
111
112#[tokio::main]
113async fn __secrets_list(
114    secrets: &Secrets,
115    opts: &SecretListOpts,
116) -> Result<Vec<docker_api::models::Secret>, docker_api::Error> {
117    secrets.list(opts).await
118}
119
120#[tokio::main]
121async fn __secrets_create(
122    secrets: &Secrets,
123    opts: &SecretCreateOpts,
124) -> Result<Secret, docker_api::Error> {
125    secrets.create(opts).await
126}
127
128#[pymethods]
129impl Pyo3Secret {
130    #[new]
131    pub fn new(docker: Pyo3Docker, id: &str) -> Self {
132        Pyo3Secret {
133            secret: Secret::new(docker.0, id),
134        }
135    }
136
137    /// Get the secret ID.
138    ///
139    /// Returns:
140    ///     str: Secret ID
141    pub fn id(&self) -> String {
142        self.secret.name().to_string()
143    }
144
145    /// Inspect the secret to get detailed information.
146    ///
147    /// Note: The secret data itself is not returned for security reasons.
148    ///
149    /// Returns:
150    ///     dict: Secret metadata including ID, version, created/updated times, and labels
151    ///
152    /// Raises:
153    ///     SystemError: If the operation fails
154    pub fn inspect(&self) -> PyResult<Py<PyAny>> {
155        let rv = __secret_inspect(&self.secret);
156
157        match rv {
158            Ok(rv) => Ok(pythonize_this!(rv)),
159            Err(rv) => Err(py_sys_exception!(rv)),
160        }
161    }
162
163    /// Delete the secret from the swarm.
164    ///
165    /// Returns:
166    ///     None
167    ///
168    /// Raises:
169    ///     SystemError: If the secret cannot be deleted
170    pub fn delete(&self) -> PyResult<()> {
171        let rv = __secret_delete(&self.secret);
172        match rv {
173            Ok(rv) => Ok(rv),
174            Err(rv) => Err(py_sys_exception!(rv)),
175        }
176    }
177}
178
179#[tokio::main]
180async fn __secret_inspect(
181    secret: &Secret,
182) -> Result<docker_api::models::Secret, docker_api::Error> {
183    secret.inspect().await
184}
185
186#[tokio::main]
187async fn __secret_delete(secret: &Secret) -> Result<(), docker_api::Error> {
188    secret.delete().await
189}