influxdb2/api/
label.rs

1//! Labels
2
3use crate::models::{LabelCreateRequest, LabelResponse, LabelUpdate, LabelsResponse};
4use crate::{Client, Http, RequestError, ReqwestProcessing, Serializing};
5use reqwest::{Method, StatusCode};
6use snafu::ResultExt;
7use std::collections::HashMap;
8
9impl Client {
10    /// List all Labels
11    pub async fn labels(&self) -> Result<LabelsResponse, RequestError> {
12        self.get_labels(None).await
13    }
14
15    /// List all Labels by organization ID
16    pub async fn labels_by_org(&self, org_id: &str) -> Result<LabelsResponse, RequestError> {
17        self.get_labels(Some(org_id)).await
18    }
19
20    async fn get_labels(&self, org_id: Option<&str>) -> Result<LabelsResponse, RequestError> {
21        let labels_url = self.url("/api/v2/labels");
22        let mut request = self.request(Method::GET, &labels_url);
23
24        if let Some(id) = org_id {
25            request = request.query(&[("orgID", id)]);
26        }
27
28        let response = request.send().await.context(ReqwestProcessing)?;
29        match response.status() {
30            StatusCode::OK => Ok(response
31                .json::<LabelsResponse>()
32                .await
33                .context(ReqwestProcessing)?),
34            status => {
35                let text = response.text().await.context(ReqwestProcessing)?;
36                Http { status, text }.fail()?
37            }
38        }
39    }
40
41    /// Retrieve a label by ID
42    pub async fn find_label(&self, label_id: &str) -> Result<LabelResponse, RequestError> {
43        let labels_by_id_url = self.url(&format!("/api/v2/labels/{}", label_id));
44        let response = self
45            .request(Method::GET, &labels_by_id_url)
46            .send()
47            .await
48            .context(ReqwestProcessing)?;
49        match response.status() {
50            StatusCode::OK => Ok(response
51                .json::<LabelResponse>()
52                .await
53                .context(ReqwestProcessing)?),
54            status => {
55                let text = response.text().await.context(ReqwestProcessing)?;
56                Http { status, text }.fail()?
57            }
58        }
59    }
60
61    /// Create a Label
62    pub async fn create_label(
63        &self,
64        org_id: &str,
65        name: &str,
66        properties: Option<HashMap<String, String>>,
67    ) -> Result<LabelResponse, RequestError> {
68        let create_label_url = self.url("/api/v2/labels");
69        let body = LabelCreateRequest {
70            org_id: org_id.into(),
71            name: name.into(),
72            properties,
73        };
74        let response = self
75            .request(Method::POST, &create_label_url)
76            .body(serde_json::to_string(&body).context(Serializing)?)
77            .send()
78            .await
79            .context(ReqwestProcessing)?;
80        match response.status() {
81            StatusCode::CREATED => Ok(response
82                .json::<LabelResponse>()
83                .await
84                .context(ReqwestProcessing)?),
85            status => {
86                let text = response.text().await.context(ReqwestProcessing)?;
87                Http { status, text }.fail()?
88            }
89        }
90    }
91
92    /// Update a Label
93    pub async fn update_label(
94        &self,
95        name: Option<String>,
96        properties: Option<HashMap<String, String>>,
97        label_id: &str,
98    ) -> Result<LabelResponse, RequestError> {
99        let update_label_url = self.url(&format!("/api/v2/labels/{}", label_id));
100        let body = LabelUpdate { name, properties };
101        let response = self
102            .request(Method::PATCH, &update_label_url)
103            .body(serde_json::to_string(&body).context(Serializing)?)
104            .send()
105            .await
106            .context(ReqwestProcessing)?;
107        match response.status() {
108            StatusCode::OK => Ok(response
109                .json::<LabelResponse>()
110                .await
111                .context(ReqwestProcessing)?),
112            status => {
113                let text = response.text().await.context(ReqwestProcessing)?;
114                Http { status, text }.fail()?
115            }
116        }
117    }
118
119    /// Delete a Label
120    pub async fn delete_label(&self, label_id: &str) -> Result<(), RequestError> {
121        let delete_label_url = self.url(&format!("/api/v2/labels/{}", label_id));
122        let response = self
123            .request(Method::DELETE, &delete_label_url)
124            .send()
125            .await
126            .context(ReqwestProcessing)?;
127        match response.status() {
128            StatusCode::NO_CONTENT => Ok(()),
129            status => {
130                let text = response.text().await.context(ReqwestProcessing)?;
131                Http { status, text }.fail()?
132            }
133        }
134    }
135}
136
137#[cfg(test)]
138mod tests {
139    use super::*;
140    use mockito::mock;
141
142    const BASE_PATH: &str = "/api/v2/labels";
143
144    #[tokio::test]
145    async fn labels() {
146        let token = "some-token";
147
148        let mock_server = mock("GET", BASE_PATH)
149            .match_header("Authorization", format!("Token {}", token).as_str())
150            .create();
151
152        let client = Client::new(mockito::server_url(), "", token);
153
154        let _result = client.labels().await;
155
156        mock_server.assert();
157    }
158
159    #[tokio::test]
160    async fn labels_by_org() {
161        let token = "some-token";
162        let org_id = "some-org_id";
163
164        let mock_server = mock("GET", format!("{}?orgID={}", BASE_PATH, org_id).as_str())
165            .match_header("Authorization", format!("Token {}", token).as_str())
166            .create();
167
168        let client = Client::new(mockito::server_url(), "", token);
169
170        let _result = client.labels_by_org(org_id).await;
171
172        mock_server.assert();
173    }
174
175    #[tokio::test]
176    async fn find_label() {
177        let token = "some-token";
178        let label_id = "some-id";
179
180        let mock_server = mock("GET", format!("{}/{}", BASE_PATH, label_id).as_str())
181            .match_header("Authorization", format!("Token {}", token).as_str())
182            .create();
183
184        let client = Client::new(mockito::server_url(), "", token);
185
186        let _result = client.find_label(label_id).await;
187
188        mock_server.assert();
189    }
190
191    #[tokio::test]
192    async fn create_label() {
193        let token = "some-token";
194        let org_id = "some-org";
195        let name = "some-user";
196        let mut properties = HashMap::new();
197        properties.insert("some-key".to_string(), "some-value".to_string());
198
199        let mock_server = mock("POST", BASE_PATH)
200            .match_header("Authorization", format!("Token {}", token).as_str())
201            .match_body(
202                format!(
203                    r#"{{"orgID":"{}","name":"{}","properties":{{"some-key":"some-value"}}}}"#,
204                    org_id, name
205                )
206                .as_str(),
207            )
208            .create();
209
210        let client = Client::new(mockito::server_url(), org_id, token);
211
212        let _result = client.create_label(org_id, name, Some(properties)).await;
213
214        mock_server.assert();
215    }
216
217    #[tokio::test]
218    async fn create_label_opt() {
219        let token = "some-token";
220        let org_id = "some-org_id";
221        let name = "some-user";
222
223        let mock_server = mock("POST", BASE_PATH)
224            .match_header("Authorization", format!("Token {}", token).as_str())
225            .match_body(format!(r#"{{"orgID":"{}","name":"{}"}}"#, org_id, name).as_str())
226            .create();
227
228        let client = Client::new(mockito::server_url(), org_id, token);
229
230        let _result = client.create_label(org_id, name, None).await;
231
232        mock_server.assert();
233    }
234
235    #[tokio::test]
236    async fn update_label() {
237        let token = "some-token";
238        let name = "some-user";
239        let label_id = "some-label_id";
240        let mut properties = HashMap::new();
241        properties.insert("some-key".to_string(), "some-value".to_string());
242
243        let mock_server = mock("PATCH", format!("{}/{}", BASE_PATH, label_id).as_str())
244            .match_header("Authorization", format!("Token {}", token).as_str())
245            .match_body(
246                format!(
247                    r#"{{"name":"{}","properties":{{"some-key":"some-value"}}}}"#,
248                    name
249                )
250                .as_str(),
251            )
252            .create();
253
254        let client = Client::new(mockito::server_url(), "", token);
255
256        let _result = client
257            .update_label(Some(name.to_string()), Some(properties), label_id)
258            .await;
259
260        mock_server.assert();
261    }
262
263    #[tokio::test]
264    async fn update_label_opt() {
265        let token = "some-token";
266        let label_id = "some-label_id";
267
268        let mock_server = mock("PATCH", format!("{}/{}", BASE_PATH, label_id).as_str())
269            .match_header("Authorization", format!("Token {}", token).as_str())
270            .match_body("{}")
271            .create();
272
273        let client = Client::new(mockito::server_url(), "", token);
274
275        let _result = client.update_label(None, None, label_id).await;
276
277        mock_server.assert();
278    }
279
280    #[tokio::test]
281    async fn delete_label() {
282        let token = "some-token";
283        let label_id = "some-label_id";
284
285        let mock_server = mock("DELETE", format!("{}/{}", BASE_PATH, label_id).as_str())
286            .match_header("Authorization", format!("Token {}", token).as_str())
287            .create();
288
289        let client = Client::new(mockito::server_url(), "", token);
290
291        let _result = client.delete_label(label_id).await;
292
293        mock_server.assert();
294    }
295}