test and troubleshoot hostconfig

This commit is contained in:
Vincent Stuyck 2025-12-20 16:37:48 +01:00
parent 8e34f31810
commit 20d0c76e7a
3 changed files with 117 additions and 13 deletions

View File

@ -3,6 +3,7 @@ use std::fmt::Display;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use crate::api::rules::contactgroups::HostContactGroups;
use crate::api::rules::snmp::SnmpCommunity;
@ -39,15 +40,33 @@ pub struct FolderAttributes {
/// this attribute is not optional when queried from the api.
/// It cannot be filled in when creating a new folder.
pub meta_data: Option<MetaData>,
#[serde(flatten, skip_serializing_if = "HashMap::is_empty")]
/// Additional attributes that can be used to categorize hosts. every tag is part of a tag_group
/// NOTE that checkmk always returns taggroups prefixed with "tag_"
// Additional attributes that can be used to categorize hosts. every tag is part of a tag_group
// NOTE that checkmk always returns taggroups prefixed with "tag_"
#[serde(default, flatten, skip_serializing_if = "HashMap::is_empty")]
pub tags: HashMap<String, String>,
// TODO: to be implemented
// #[serde(flatten, default)]
// pub networkscan: NetworkScan,
// #[serde(flatten, default)]
// pub management: ManagementProtocol,
// these fields are used to prevent tags from taking them up
#[serde(default)]
management_snmp_community: Option<SnmpCommunity>,
#[serde(default, skip_serializing)]
management_address: Value,
#[serde(default, skip_serializing)]
management_protocol: Value,
#[serde(default, skip_serializing)]
management_ipmi_credentials: Value,
#[serde(default, skip_serializing)]
network_scan: Value,
#[serde(default, skip_serializing)]
network_scan_result: Value,
#[serde(default, skip_serializing)]
waiting_for_discovery: Value,
#[serde(default, skip_serializing)]
inventory_failed: Value,
#[serde(default, skip_serializing)]
locked_attributes: Value,
#[serde(default, skip_serializing)]
locked_by: Value,
}
impl FolderAttributes {
@ -93,7 +112,7 @@ impl FolderAttributes {
pub fn add_tag(&mut self, taggroup: impl Display, tagvalue: String) {
self.tags
.insert(format!("tag_{taggroup}"), tagvalue.to_string());
.insert(format!("tag_{taggroup}"), tagvalue);
}
pub fn with_tag(mut self, taggroup: impl Display, tagvalue: String) -> Self {
self.add_tag(taggroup, tagvalue);

View File

@ -1,3 +1,5 @@
use std::net::{Ipv4Addr, Ipv6Addr};
use serde::{Deserialize, Serialize};
use crate::api::folders::FolderAttributes;
@ -16,13 +18,31 @@ impl Client {
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct HostConfig {
pub folder: String,
pub attributes: FolderAttributes,
pub effective_attributes: FolderAttributes,
pub attributes: HostAttributes,
pub effective_attributes: HostAttributes,
pub is_cluster: bool,
pub is_offline: bool,
pub cluster_nodes: Option<Vec<String>>,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct HostAttributes {
#[serde(default)]
alias: Option<String>,
#[serde(default)]
ipaddress: Option<String>,
#[serde(default)]
ipv6address: Option<String>,
#[serde(default)]
additional_ipv4addresses: Vec<Ipv4Addr>,
#[serde(default)]
additional_ipv6addresses: Vec<Ipv6Addr>,
#[serde(flatten, default)]
folder_attributes: FolderAttributes
}
impl DomainExtension for HostConfig {
const DOMAIN_TYPE: super::DomainType = super::DomainType::HostConfig;
@ -35,7 +55,7 @@ impl DomainExtension for HostConfig {
#[derive(Serialize)]
pub struct HostCreationRequest {
pub hostname: String,
pub host_name: String,
pub folder: String,
pub attributes: FolderAttributes,
}
@ -60,7 +80,7 @@ pub struct HostUpdateRequest {
impl HostCreationRequest {
pub fn new(hostname: String, folder: String, attributes: FolderAttributes) -> Self {
HostCreationRequest {
hostname,
host_name: hostname,
folder,
attributes,
}

View File

@ -24,6 +24,7 @@ async fn main() -> Result<()> {
.unwrap();
test_folders(client.clone()).await?;
test_hosts(client.clone()).await?;
Ok(())
}
@ -48,11 +49,13 @@ async fn test_folders(client: Client) -> Result<()> {
.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)
@ -64,6 +67,7 @@ async fn test_folders(client: Client) -> Result<()> {
.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
@ -77,3 +81,64 @@ async fn test_folders(client: Client) -> Result<()> {
Ok(())
}
async fn test_hosts(client: Client) -> Result<()> {
use checkmk_api::api::hosts::*;
use checkmk_api::api::folders::FolderAttributes;
const TESTHOST: &str = "test-host";
info!("testing hosts");
let hostapi = client.host_api();
let creq = HostCreationRequest::new(
TESTHOST.to_string(),
"~".to_string(),
FolderAttributes::default().with_site("dev".to_string())
);
let cquery = HostCreationQuery::new(false);
let rquery = HostReadQuery::new(true);
let ureq1 = HostUpdateRequest::replace(
FolderAttributes::default()
.with_site("dev".to_string())
.with_label("environment".to_string(), "test".to_string())
);
let ureq2 = HostUpdateRequest::update(
FolderAttributes::default().with_label("purpose".to_string(), "testing".to_string())
);
info!("creating test host");
hostapi
.create(&creq, &cquery)
.await
.inspect_err(|e| error!("failed to create host: {e}"))?;
let host = hostapi
.read(TESTHOST, &rquery)
.await
.inspect_err(|e| error!("failed to read host: {e}"))?;
info!("host config: {host:#?}");
info!("updating host");
hostapi
.update(TESTHOST, &ureq1)
.await
.inspect_err(|e| error!("failed to update host: {e}"))?;
let hosts = hostapi
.bulk_read(&HostBulkReadQuery::new().with_effective_attributes(true))
.await
.inspect_err(|e| error!("failed to read all hosts: {e}"));
info!("all hosts: {hosts:?}");
hostapi
.bulk_update(&[HostBulkUpdateRequest::new(TESTHOST.to_string(), ureq2)])
.await
.inspect_err(|e| error!("failed to do a bulk update of hosts: {e}"))?;
info!("deleting host");
hostapi
.delete(TESTHOST, &())
.await
.inspect_err(|e| error!("failed to delete host: {e}"))?;
Ok(())
}