add rulesets api

This commit is contained in:
Vincent Stuyck 2026-02-28 19:22:06 +01:00
parent 6de616e8ab
commit 804faa6273
4 changed files with 187 additions and 9 deletions

View File

@ -2,6 +2,7 @@ pub mod activations;
pub mod folders;
pub mod groups;
pub mod hosts;
pub mod rules;
pub mod tags;
use std::fmt::{self, Display};
@ -22,6 +23,9 @@ pub enum DomainType {
ServiceGroupConfig,
HostTagGroup,
ActivationRun,
Ruleset,
Rule,
Dict
}
impl fmt::Display for DomainType {
@ -35,6 +39,9 @@ impl fmt::Display for DomainType {
DomainType::ServiceGroupConfig => write!(f, "service_group_config"),
DomainType::HostTagGroup => write!(f, "host_tag_group"),
DomainType::ActivationRun => write!(f, "activation_run"),
DomainType::Ruleset => write!(f, "ruleset"),
DomainType::Rule => write!(f, "rule"),
DomainType::Dict => write!(f, "dict"),
}
}
}

138
src/api/rules.rs Normal file
View File

@ -0,0 +1,138 @@
use std::fmt::Display;
use serde::{Deserialize, Serialize};
#[cfg(feature = "schemars")]
use schemars::JsonSchema;
use crate::api::{DomainExtension, DomainObject, domain_bulk_read, domain_client};
use crate::{ApiClient, Client, Result};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
pub struct Ruleset {
pub name: String,
pub title: String,
// this value is not set when searching for a specific ruleset (dont ask me why)
pub help: Option<String>,
// this value should be set, but never is. wrong documentation?
pub folder: Option<String>,
// this value is not set when searching for a specific ruleset (dont ask me why)
pub item_type: Option<String>,
// this value is not set when searching for a specific ruleset (dont ask me why)
pub item_name: Option<String>,
// now sure what this is supposed to be right now. no documentation
// item_enum: Option<()>,
// this value is not set when searching for a specific ruleset (dont ask me why)
pub match_type: Option<MatchType>,
pub number_of_rules: usize
}
impl DomainExtension for Ruleset {
const DOMAIN_TYPE: super::DomainType = super::DomainType::Ruleset;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
#[serde(rename_all = "snake_case")]
pub enum MatchType {
All,
First,
Dict,
List,
Varies
}
domain_client!(Ruleset, ruleset_api);
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
pub struct RulesetQuery {
name: Option<String>,
fulltext: Option<String>,
folder: Option<String>,
deprecated: bool,
used: bool,
}
impl RulesetQuery {
pub fn set_name(&mut self, name: String) {
self.name = Some(name);
}
pub fn with_name(mut self, name: String) -> Self {
self.set_name(name);
self
}
pub fn set_fulltext(&mut self, fulltext: String) {
self.fulltext = Some(fulltext);
}
pub fn with_fulltext(mut self, fulltext: String) -> Self {
self.set_fulltext(fulltext);
self
}
pub fn set_folder(&mut self, folder: String) {
self.folder = Some(folder);
}
pub fn with_folder(mut self, folder: String) -> Self {
self.set_folder(folder);
self
}
pub fn set_deprecated(&mut self, deprecated: bool) {
self.deprecated = deprecated;
}
pub fn with_deprecated(mut self, deprecated: bool) -> Self {
self.set_deprecated(deprecated);
self
}
pub fn set_used(&mut self, used: bool) {
self.used = used;
}
pub fn with_used(mut self, used: bool) -> Self {
self.set_used(used);
self
}
}
impl ApiClient<Ruleset> {
pub async fn read(&self, id: impl Display) -> Result<Ruleset> {
#[derive(Deserialize, Serialize)]
struct RulesetCompact {
name: String,
folder: Option<String>,
number_of_rules: usize
}
impl DomainExtension for RulesetCompact {
const DOMAIN_TYPE: super::DomainType = super::DomainType::Ruleset;
}
impl From<DomainObject<RulesetCompact>> for Ruleset {
fn from(value: DomainObject<RulesetCompact>) -> Self {
Ruleset {
name: value.extensions.name,
folder: value.extensions.folder,
number_of_rules: value.extensions.number_of_rules,
title: value.title.unwrap_or_default(),
help: None,
item_type: None,
item_name: None,
match_type: None,
}
}
}
self.inner
.read_domain_object::<RulesetCompact, _>(id, &())
.await
.map(|obj| obj.into())
}
}
domain_bulk_read!(Ruleset, RulesetQuery);

View File

@ -222,15 +222,9 @@ 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()
);
if let Some(body) = request.body().as_ref().and_then(|b| b.as_bytes()) {
trace!("with body: {}", String::from_utf8_lossy(body))
}
let response = self
.http

View File

@ -33,6 +33,7 @@ async fn main() -> Result<()> {
test_host_groups(client.clone()).await?;
test_service_groups(client.clone()).await?;
test_contact_groups(client.clone()).await?;
test_rulesets(client.clone()).await?;
test_activations(client.clone()).await?;
info!("tests done; all pass");
@ -394,6 +395,44 @@ async fn test_activations(client: Client) -> Result<()> {
Ok(())
}
async fn test_rulesets(client: Client) -> Result<()> {
use checkmk_api::api::rules::*;
const KNOWN_RULESET: &str = "inv_exports:software_csv";
info!("testing rulesets");
let api = client.ruleset_api();
info!("reading single ruleset '{KNOWN_RULESET}'");
let ruleset = api
.read(KNOWN_RULESET)
.await
.inspect_err(|e| error!("failed to read ruleset: {e}"))?;
info!("ruleset: {ruleset:#?}");
info!("bulk reading all rulesets");
let all = api
.bulk_read(&RulesetQuery::default())
.await
.inspect_err(|e| error!("failed to bulk read rulesets: {e}"))?;
info!("total rulesets: {}", all.len());
info!("bulk reading only used rulesets");
let used = api
.bulk_read(&RulesetQuery::default().with_used(true))
.await
.inspect_err(|e| error!("failed to bulk read used rulesets: {e}"))?;
info!("used rulesets: {}", used.len());
info!("bulk reading rulesets with fulltext search");
let search = api
.bulk_read(&RulesetQuery::default().with_fulltext("memory".to_string()))
.await
.inspect_err(|e| error!("failed to bulk read rulesets by fulltext: {e}"))?;
info!("rulesets matching 'memory': {}", search.len());
Ok(())
}
async fn test_contact_groups(client: Client) -> Result<()> {
use checkmk_api::api::groups::*;
const TESTGROUP: &str = "test-contact-group";