feat: Add support for labels API to influxdb_client
List all Labels Retrieve a label by ID Create a Label Update a Label Delete a Label Add examples and test Add necessary models Signed-off-by: jeivardan <jeivardanvenkatesh@gmail.com>pull/24376/head
parent
5750a69c75
commit
ba5935f0bd
|
@ -0,0 +1,26 @@
|
|||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let influx_url = "http://localhost:8888";
|
||||
let token = "some-token";
|
||||
|
||||
let client = influxdb2_client::Client::new(influx_url, token);
|
||||
|
||||
println!("{:?}", client.find_labels().await?);
|
||||
println!("{:?}", client.find_label_by_id("some-label_id").await?);
|
||||
let mut properties = std::collections::HashMap::new();
|
||||
properties.insert("some-key".to_string(), "some-value".to_string());
|
||||
println!(
|
||||
"{:?}",
|
||||
client
|
||||
.create_label("some-org_id", "some-name", Some(properties))
|
||||
.await?
|
||||
);
|
||||
println!(
|
||||
"{:?}",
|
||||
client
|
||||
.update_label(Some("some-name".to_string()), None, "some-label_id")
|
||||
.await?
|
||||
);
|
||||
println!("{:?}", client.delete_label("some-label_id").await?);
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
use crate::models::{LabelCreateRequest, LabelResponse, LabelUpdate, LabelsResponse};
|
||||
use crate::{Client, Http, RequestError, ReqwestProcessing, Serializing};
|
||||
use reqwest::{Method, StatusCode};
|
||||
use snafu::ResultExt;
|
||||
|
||||
impl Client {
|
||||
/// List all Labels
|
||||
pub async fn find_labels(&self) -> Result<LabelsResponse, RequestError> {
|
||||
let labels_url = format!("{}/api/v2/labels", self.url);
|
||||
let response = self
|
||||
.request(Method::GET, &labels_url)
|
||||
.send()
|
||||
.await
|
||||
.context(ReqwestProcessing)?;
|
||||
match response.status() {
|
||||
StatusCode::OK => Ok(response
|
||||
.json::<LabelsResponse>()
|
||||
.await
|
||||
.context(ReqwestProcessing)?),
|
||||
status => {
|
||||
let text = response.text().await.context(ReqwestProcessing)?;
|
||||
Http { status, text }.fail()?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieve a label by ID
|
||||
pub async fn find_label_by_id(&self, label_id: &str) -> Result<LabelResponse, RequestError> {
|
||||
let labels_by_id_url = format!("{}/api/v2/labels/{}", self.url, label_id);
|
||||
let response = self
|
||||
.request(Method::GET, &labels_by_id_url)
|
||||
.send()
|
||||
.await
|
||||
.context(ReqwestProcessing)?;
|
||||
match response.status() {
|
||||
StatusCode::OK => Ok(response
|
||||
.json::<LabelResponse>()
|
||||
.await
|
||||
.context(ReqwestProcessing)?),
|
||||
status => {
|
||||
let text = response.text().await.context(ReqwestProcessing)?;
|
||||
Http { status, text }.fail()?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a Label
|
||||
pub async fn create_label(
|
||||
&self,
|
||||
org_id: &str,
|
||||
name: &str,
|
||||
properties: Option<::std::collections::HashMap<String, String>>,
|
||||
) -> Result<LabelResponse, RequestError> {
|
||||
let create_label_url = format!("{}/api/v2/labels", self.url);
|
||||
let body = LabelCreateRequest {
|
||||
org_id: org_id.into(),
|
||||
name: name.into(),
|
||||
properties,
|
||||
};
|
||||
let response = self
|
||||
.request(Method::POST, &create_label_url)
|
||||
.body(serde_json::to_string(&body).context(Serializing)?)
|
||||
.send()
|
||||
.await
|
||||
.context(ReqwestProcessing)?;
|
||||
match response.status() {
|
||||
StatusCode::CREATED => Ok(response
|
||||
.json::<LabelResponse>()
|
||||
.await
|
||||
.context(ReqwestProcessing)?),
|
||||
status => {
|
||||
let text = response.text().await.context(ReqwestProcessing)?;
|
||||
Http { status, text }.fail()?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Update a Label
|
||||
pub async fn update_label(
|
||||
&self,
|
||||
name: Option<String>,
|
||||
properties: Option<::std::collections::HashMap<String, String>>,
|
||||
label_id: &str,
|
||||
) -> Result<LabelResponse, RequestError> {
|
||||
let update_label_url = format!("{}/api/v2/labels/{}", &self.url, label_id);
|
||||
let body = LabelUpdate { name, properties };
|
||||
let response = self
|
||||
.request(Method::PATCH, &update_label_url)
|
||||
.body(serde_json::to_string(&body).context(Serializing)?)
|
||||
.send()
|
||||
.await
|
||||
.context(ReqwestProcessing)?;
|
||||
match response.status() {
|
||||
StatusCode::OK => Ok(response
|
||||
.json::<LabelResponse>()
|
||||
.await
|
||||
.context(ReqwestProcessing)?),
|
||||
status => {
|
||||
let text = response.text().await.context(ReqwestProcessing)?;
|
||||
Http { status, text }.fail()?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete a Label
|
||||
pub async fn delete_label(&self, label_id: &str) -> Result<(), RequestError> {
|
||||
let delete_label_url = format!("{}/api/v2/labels/{}", &self.url, label_id);
|
||||
let response = self
|
||||
.request(Method::DELETE, &delete_label_url)
|
||||
.send()
|
||||
.await
|
||||
.context(ReqwestProcessing)?;
|
||||
match response.status() {
|
||||
StatusCode::NO_CONTENT => Ok(()),
|
||||
status => {
|
||||
let text = response.text().await.context(ReqwestProcessing)?;
|
||||
Http { status, text }.fail()?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use mockito::mock;
|
||||
|
||||
type Error = Box<dyn std::error::Error>;
|
||||
type Result<T = (), E = Error> = std::result::Result<T, E>;
|
||||
|
||||
#[tokio::test]
|
||||
async fn find_labels() -> Result {
|
||||
let token = "some-token";
|
||||
|
||||
let mock_server = mock("GET", "/api/v2/labels")
|
||||
.match_header("Authorization", format!("Token {}", token).as_str())
|
||||
.create();
|
||||
|
||||
let client = Client::new(&mockito::server_url(), token);
|
||||
|
||||
let _result = client.find_labels().await;
|
||||
|
||||
mock_server.assert();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn find_label_by_id() -> Result {
|
||||
let token = "some-token";
|
||||
let label_id = "some-id";
|
||||
let mock_server = mock("GET", format!("/api/v2/labels/{}", label_id).as_str())
|
||||
.match_header("Authorization", format!("Token {}", token).as_str())
|
||||
.create();
|
||||
|
||||
let client = Client::new(&mockito::server_url(), token);
|
||||
|
||||
let _result = client.find_label_by_id(label_id).await;
|
||||
|
||||
mock_server.assert();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_label() -> Result {
|
||||
let token = "some-token";
|
||||
let org_id = "some-org";
|
||||
let name = "some-user";
|
||||
let mut properties = std::collections::HashMap::new();
|
||||
properties.insert("some-key".to_string(), "some-value".to_string());
|
||||
|
||||
let mock_server = mock("POST", "/api/v2/labels")
|
||||
.match_header("Authorization", format!("Token {}", token).as_str())
|
||||
.match_body(
|
||||
format!(
|
||||
r#"{{"org_id":"{}","name":"{}","properties":"{:?}"}}"#,
|
||||
org_id, name, properties
|
||||
)
|
||||
.as_str(),
|
||||
)
|
||||
.create();
|
||||
|
||||
let client = Client::new(&mockito::server_url(), token);
|
||||
|
||||
let _result = client.create_label(org_id, name, Some(properties)).await;
|
||||
|
||||
mock_server.assert();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn create_label_opt() -> Result {
|
||||
let token = "some-token";
|
||||
let org_id = "some-org_id";
|
||||
let name = "some-user";
|
||||
|
||||
let mock_server = mock("POST", "/api/v2/labels")
|
||||
.match_header("Authorization", format!("Token {}", token).as_str())
|
||||
.match_body(format!(r#"{{"org_id":"{}","name":"{}"}}"#, org_id, name).as_str())
|
||||
.create();
|
||||
|
||||
let client = Client::new(&mockito::server_url(), token);
|
||||
|
||||
let _result = client.create_label(org_id, name, None).await;
|
||||
|
||||
mock_server.assert();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn update_label() -> Result {
|
||||
let token = "some-token";
|
||||
let name = "some-user";
|
||||
let label_id = "some-label_id";
|
||||
let mut properties = std::collections::HashMap::new();
|
||||
properties.insert("some-key".to_string(), "some-value".to_string());
|
||||
|
||||
let mock_server = mock("PATCH", format!("/api/v2/labels/{}", label_id).as_str())
|
||||
.match_header("Authorization", format!("Token {}", token).as_str())
|
||||
.match_body(
|
||||
format!(r#"{{"name":"{}","properties":"{:?}"}}"#, name, properties).as_str(),
|
||||
)
|
||||
.create();
|
||||
|
||||
let client = Client::new(&mockito::server_url(), token);
|
||||
|
||||
let _result = client
|
||||
.update_label(Some(name.to_string()), Some(properties), label_id)
|
||||
.await;
|
||||
|
||||
mock_server.assert();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn update_label_opt() -> Result {
|
||||
let token = "some-token";
|
||||
let label_id = "some-label_id";
|
||||
|
||||
let mock_server = mock("PATCH", format!("/api/v2/labels/{}", label_id).as_str())
|
||||
.match_header("Authorization", format!("Token {}", token).as_str())
|
||||
.match_body("{}")
|
||||
.create();
|
||||
|
||||
let client = Client::new(&mockito::server_url(), token);
|
||||
|
||||
let _result = client.update_label(None, None, label_id).await;
|
||||
|
||||
mock_server.assert();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn delete_label() -> Result {
|
||||
let token = "some-token";
|
||||
let label_id = "some-label_id";
|
||||
|
||||
let mock_server = mock("DELETE", format!("/api/v2/labels/{}", label_id).as_str())
|
||||
.match_header("Authorization", format!("Token {}", token).as_str())
|
||||
.create();
|
||||
|
||||
let client = Client::new(&mockito::server_url(), token);
|
||||
|
||||
let _result = client.delete_label(label_id).await;
|
||||
|
||||
mock_server.assert();
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Post create label request, to create a new label
|
||||
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LabelCreateRequest {
|
||||
/// Organisation ID
|
||||
#[serde(rename = "orgID")]
|
||||
pub org_id: String,
|
||||
/// Organisation name
|
||||
pub name: String,
|
||||
/// Key/Value pairs associated with properties.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub properties: Option<::std::collections::HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl LabelCreateRequest {
|
||||
/// Return instance of LabelCreateRequest
|
||||
pub fn new(org_id: String, name: String) -> Self {
|
||||
Self {
|
||||
org_id,
|
||||
name,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// LabelResponse
|
||||
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LabelResponse {
|
||||
/// Label
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub label: Option<crate::models::Label>,
|
||||
/// Links
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub links: Option<crate::models::Links>,
|
||||
}
|
||||
|
||||
impl LabelResponse {
|
||||
/// Returns instance of LabelResponse
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
///LabelsResponse
|
||||
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LabelsResponse {
|
||||
/// Labels
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub labels: Vec<crate::models::Label>,
|
||||
/// Links
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub links: Option<crate::models::Links>,
|
||||
}
|
||||
|
||||
impl LabelsResponse {
|
||||
/// Returns List of Labels
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
///LabelUpdateRequest
|
||||
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct LabelUpdate {
|
||||
/// Name
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
/// Key/Value pairs associated with properties.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub properties: Option<::std::collections::HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl LabelUpdate {
|
||||
/// Returns an instance of LabelUpdate
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Label
|
||||
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Label {
|
||||
/// Label ID
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub id: Option<String>,
|
||||
/// Org ID
|
||||
#[serde(rename = "orgID", skip_serializing_if = "Option::is_none")]
|
||||
pub org_id: Option<String>,
|
||||
/// Label name
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub name: Option<String>,
|
||||
/// Key/Value pairs associated with properties.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub properties: Option<::std::collections::HashMap<String, String>>,
|
||||
}
|
||||
|
||||
impl Label {
|
||||
/// Returns an instance of Label
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
//! Links
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Links
|
||||
#[derive(Clone, Debug, PartialEq, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Links {
|
||||
/// URI of resource.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub next: Option<String>,
|
||||
/// URI of resource.
|
||||
#[serde(rename = "self")]
|
||||
pub self_: String,
|
||||
/// URI of resource.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub prev: Option<String>,
|
||||
}
|
||||
|
||||
impl Links {
|
||||
/// Returns instance of Links
|
||||
pub fn new(self_: String) -> Self {
|
||||
Self {
|
||||
self_,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue