test and troubleshoot bulk requests
This commit is contained in:
parent
fddc74ef27
commit
0b0fa24078
@ -5,7 +5,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Client;
|
||||
use crate::api::DomainExtention;
|
||||
use crate::api::{BulkReadDomainExtention, BulkUpdateDomainExtention, DomainExtention};
|
||||
use crate::api::rules::contactgroups::HostContactGroups;
|
||||
use crate::api::rules::snmp::SnmpCommunity;
|
||||
use crate::client::ApiClient;
|
||||
@ -87,8 +87,8 @@ impl FolderAttributes {
|
||||
pub fn add_label(&mut self, labelkey: String, labelvalue: String) {
|
||||
self.labels.insert(labelkey, labelvalue);
|
||||
}
|
||||
pub fn with_label(mut self, taggroup: String, tagvalue: String) -> Self {
|
||||
self.add_label(taggroup, tagvalue);
|
||||
pub fn with_label(mut self, labelkey: String, labelvalue: String) -> Self {
|
||||
self.add_label(labelkey, labelvalue);
|
||||
self
|
||||
}
|
||||
|
||||
@ -114,8 +114,8 @@ impl DomainExtention for FolderConfig {
|
||||
const DOMAIN_TYPE: super::DomainType = super::DomainType::FolderConfig;
|
||||
|
||||
type CreationRequest = FolderCreationRequest;
|
||||
type CreationQuery = FolderCreationQuery;
|
||||
type ReadQuery = FolderReadQuery;
|
||||
type CreationQuery = ();
|
||||
type ReadQuery = ();
|
||||
type UpdateRequest = FolderUpdateRequest;
|
||||
type DeleteQuery = FolderDeleteQuery;
|
||||
}
|
||||
@ -146,6 +146,7 @@ pub struct FolderReadQuery;
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct FolderUpdateRequest {
|
||||
#[serde(skip_serializing_if = "String::is_empty")]
|
||||
pub title: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub attributes: Option<FolderAttributes>,
|
||||
@ -156,30 +157,46 @@ pub struct FolderUpdateRequest {
|
||||
}
|
||||
|
||||
impl FolderUpdateRequest {
|
||||
pub fn replace(title: String, attributes: FolderAttributes) -> Self {
|
||||
pub fn replace(attributes: FolderAttributes) -> Self {
|
||||
Self {
|
||||
title,
|
||||
title: String::new(),
|
||||
attributes: Some(attributes),
|
||||
update_attributes: None,
|
||||
remove_attributes: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn update(title: String, attributes: FolderAttributes) -> Self {
|
||||
pub fn update(attributes: FolderAttributes) -> Self {
|
||||
Self {
|
||||
title,
|
||||
title: String::new(),
|
||||
attributes: None,
|
||||
update_attributes: Some(attributes),
|
||||
remove_attributes: Vec::new(),
|
||||
}
|
||||
}
|
||||
pub fn remove(title: String, attributes: Vec<String>) -> Self {
|
||||
pub fn remove(attributes: Vec<String>) -> Self {
|
||||
Self {
|
||||
title,
|
||||
title: String::new(),
|
||||
attributes: None,
|
||||
update_attributes: None,
|
||||
remove_attributes: attributes,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn title(title: String) -> Self {
|
||||
Self {
|
||||
title,
|
||||
attributes: None,
|
||||
update_attributes: None,
|
||||
remove_attributes: Vec::new()
|
||||
}
|
||||
}
|
||||
pub fn set_title(&mut self, title: String) {
|
||||
self.title = title;
|
||||
}
|
||||
pub fn with_title(mut self, title: String) -> Self {
|
||||
self.set_title(title);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize)]
|
||||
@ -200,3 +217,36 @@ pub enum FolderDeleteMode {
|
||||
Recursive,
|
||||
AbotyOnNonEmpty,
|
||||
}
|
||||
|
||||
impl BulkReadDomainExtention for FolderConfig {
|
||||
type BulkReadQuery = FolderBulkReadQuery;
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FolderBulkReadQuery {
|
||||
pub parent: String,
|
||||
pub recursive: bool,
|
||||
}
|
||||
|
||||
impl FolderBulkReadQuery {
|
||||
pub fn new(parent: String, recursive: bool) -> Self {
|
||||
Self { parent, recursive }
|
||||
}
|
||||
}
|
||||
|
||||
impl BulkUpdateDomainExtention for FolderConfig {
|
||||
type BulkUpdateRequest = FolderBulkUpdateRequest;
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct FolderBulkUpdateRequest {
|
||||
folder: String,
|
||||
#[serde(flatten)]
|
||||
update_request: FolderUpdateRequest
|
||||
}
|
||||
|
||||
impl FolderBulkUpdateRequest {
|
||||
pub fn new(folder: String, update_request: FolderUpdateRequest) -> Self {
|
||||
Self { folder, update_request }
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,7 +93,9 @@ pub trait DomainExtention: DeserializeOwned + Serialize {
|
||||
// these are essentials tags for domain extentions to signal that bulk operations are possible
|
||||
// not every extention supports bulk operations. and not all extentions that do support all of them
|
||||
pub trait BulkCreateDomainExtention: DomainExtention {}
|
||||
pub trait BulkReadDomainExtention: DomainExtention {}
|
||||
pub trait BulkReadDomainExtention: DomainExtention {
|
||||
type BulkReadQuery: Serialize;
|
||||
}
|
||||
pub trait BulkUpdateDomainExtention: DomainExtention {
|
||||
type BulkUpdateRequest: Serialize;
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ use std::sync::Arc;
|
||||
use log::{debug, trace};
|
||||
use reqwest::header::{HeaderName, HeaderValue};
|
||||
use reqwest::{Certificate, Request};
|
||||
use serde::Serialize;
|
||||
use serde::de::DeserializeOwned;
|
||||
use tokio::sync::Semaphore;
|
||||
|
||||
@ -221,6 +222,14 @@ impl InnerClient {
|
||||
pub(crate) async fn handle_request(&self, request: Request) -> Result<String> {
|
||||
let permit = self.semaphore.acquire().await.unwrap();
|
||||
debug!("sending {}-request to {}", request.method(), request.url());
|
||||
trace!(
|
||||
"with body: {}",
|
||||
request.body()
|
||||
.as_ref()
|
||||
.and_then(|b| b.as_bytes())
|
||||
.map(String::from_utf8_lossy)
|
||||
.unwrap_or_default()
|
||||
);
|
||||
|
||||
let response = self
|
||||
.http
|
||||
@ -351,7 +360,7 @@ impl InnerClient {
|
||||
}
|
||||
pub(crate) async fn bulk_read_domain_objects<E: BulkReadDomainExtention>(
|
||||
&self,
|
||||
query: &E::ReadQuery,
|
||||
query: &E::BulkReadQuery,
|
||||
) -> Result<Vec<DomainObject<E>>> {
|
||||
let request = self
|
||||
.http
|
||||
@ -365,12 +374,17 @@ impl InnerClient {
|
||||
}
|
||||
pub(crate) async fn bulk_update_domain_objects<E: BulkUpdateDomainExtention>(
|
||||
&self,
|
||||
body: &[E::BulkUpdateRequest],
|
||||
entries: &[E::BulkUpdateRequest],
|
||||
) -> Result<()> {
|
||||
#[derive(Serialize)]
|
||||
struct Request<'a, D: BulkUpdateDomainExtention> {
|
||||
entries: &'a [D::BulkUpdateRequest]
|
||||
}
|
||||
|
||||
let request = self
|
||||
.http
|
||||
.put(self.bulk_action_url(E::DOMAIN_TYPE, BulkAction::Update))
|
||||
.json(body)
|
||||
.json(&Request::<E>{ entries })
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
@ -458,7 +472,7 @@ impl<D: BulkCreateDomainExtention> ApiClient<D> {
|
||||
}
|
||||
|
||||
impl<D: BulkReadDomainExtention> ApiClient<D> {
|
||||
pub async fn bulk_read(&self, query: &D::ReadQuery) -> Result<Vec<D>> {
|
||||
pub async fn bulk_read(&self, query: &D::BulkReadQuery) -> Result<Vec<D>> {
|
||||
let objs = self.inner.bulk_read_domain_objects::<D>(query).await?;
|
||||
let exts = objs.into_iter().map(|obj| obj.extensions).collect();
|
||||
Ok(exts)
|
||||
@ -466,8 +480,8 @@ impl<D: BulkReadDomainExtention> ApiClient<D> {
|
||||
}
|
||||
|
||||
impl<D: BulkUpdateDomainExtention> ApiClient<D> {
|
||||
pub async fn bulk_update(&self, request: &[D::BulkUpdateRequest]) -> Result<()> {
|
||||
self.inner.bulk_update_domain_objects::<D>(request).await
|
||||
pub async fn bulk_update(&self, entries: &[D::BulkUpdateRequest]) -> Result<()> {
|
||||
self.inner.bulk_update_domain_objects::<D>(entries).await
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
76
src/main.rs
Normal file
76
src/main.rs
Normal file
@ -0,0 +1,76 @@
|
||||
|
||||
use checkmk_api::{Client, Result};
|
||||
use log::{error, info};
|
||||
|
||||
const HOSTNAME: &str = "shion.stuyckv.local";
|
||||
const SITENAME: &str = "dev";
|
||||
const USERNAME: &str = "cmkadmin";
|
||||
const PASSWORD: &str = "C5t71DUPAu2D";
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
simplelog::TermLogger::init(
|
||||
simplelog::LevelFilter::Trace,
|
||||
simplelog::Config::default(),
|
||||
simplelog::TerminalMode::Stderr,
|
||||
simplelog::ColorChoice::Auto
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let client = Client::builder()
|
||||
.on_host_and_site(HOSTNAME.to_string(), SITENAME.to_string())
|
||||
.with_credentials(USERNAME.to_string(), PASSWORD.to_string())
|
||||
.without_ssl()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
test_folders(client.clone()).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn test_folders(client: Client) -> Result<()> {
|
||||
use checkmk_api::api::folders::*;
|
||||
const TESTDIR: &str = "test";
|
||||
const TESTDIRQRY: &str = "~test";
|
||||
info!("testing folders");
|
||||
|
||||
let folderapi = client.folder_api();
|
||||
let creq = FolderCreationRequest::new(
|
||||
TESTDIR.to_string(),
|
||||
"Testing".to_string(),
|
||||
ROOT_FOLDER.to_string(),
|
||||
FolderAttributes::default()
|
||||
);
|
||||
let ureq1 = FolderUpdateRequest::replace(
|
||||
FolderAttributes::default()
|
||||
.with_site("dev".to_string())
|
||||
);
|
||||
let ureq2 = FolderUpdateRequest::update(
|
||||
FolderAttributes::default()
|
||||
.with_label("test".to_string(), "testing".to_string())
|
||||
);
|
||||
|
||||
info!("creating testfolder");
|
||||
folderapi.create(&creq, &()).await
|
||||
.inspect_err(|e| error!("failed to create folder: {e}"))?;
|
||||
let folder = folderapi.read(TESTDIRQRY, &()).await
|
||||
.inspect_err(|e| error!("failed to read folder: {e}"))?;
|
||||
info!("folder config on site: {folder:?}");
|
||||
info!("updating folder");
|
||||
folderapi.update(TESTDIRQRY, &ureq1).await
|
||||
.inspect_err(|e| error!("failed to update folder: {e}"))?;
|
||||
|
||||
let folders = folderapi.bulk_read(&FolderBulkReadQuery::new("~".to_string(), false)).await
|
||||
.inspect_err(|e| error!("failed to read all folders: {e}"));
|
||||
info!("folder config on site: {folders:?}");
|
||||
folderapi.bulk_update(&[FolderBulkUpdateRequest::new(TESTDIRQRY.to_string(), ureq2)]).await
|
||||
.inspect_err(|e| error!("failed to do a bulk update of folders: {e}"))?;
|
||||
|
||||
info!("deleting folder");
|
||||
folderapi.delete(TESTDIRQRY, &FolderDeleteQuery::default()).await
|
||||
.inspect_err(|e| error!("failed to delete folder: {e}"))?;
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user