Compare commits
2 Commits
62fca534a1
...
20d0c76e7a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20d0c76e7a | ||
|
|
8e34f31810 |
@ -3,10 +3,11 @@ use std::fmt::Display;
|
|||||||
|
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::api::rules::contactgroups::HostContactGroups;
|
use crate::api::rules::contactgroups::HostContactGroups;
|
||||||
use crate::api::rules::snmp::SnmpCommunity;
|
use crate::api::rules::snmp::SnmpCommunity;
|
||||||
use crate::api::{BulkReadDomainExtention, BulkUpdateDomainExtention, DomainExtention};
|
use crate::api::{BulkReadDomainExtension, BulkUpdateDomainExtension, DomainExtension};
|
||||||
use crate::{ApiClient, Client, Result};
|
use crate::{ApiClient, Client, Result};
|
||||||
|
|
||||||
pub const ROOT_FOLDER: &str = "/";
|
pub const ROOT_FOLDER: &str = "/";
|
||||||
@ -39,15 +40,33 @@ pub struct FolderAttributes {
|
|||||||
/// this attribute is not optional when queried from the api.
|
/// this attribute is not optional when queried from the api.
|
||||||
/// It cannot be filled in when creating a new folder.
|
/// It cannot be filled in when creating a new folder.
|
||||||
pub meta_data: Option<MetaData>,
|
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
|
||||||
/// 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_"
|
||||||
/// NOTE that checkmk always returns taggroups prefixed with "tag_"
|
#[serde(default, flatten, skip_serializing_if = "HashMap::is_empty")]
|
||||||
pub tags: HashMap<String, String>,
|
pub tags: HashMap<String, String>,
|
||||||
// TODO: to be implemented
|
|
||||||
// #[serde(flatten, default)]
|
|
||||||
// pub networkscan: NetworkScan,
|
// these fields are used to prevent tags from taking them up
|
||||||
// #[serde(flatten, default)]
|
#[serde(default)]
|
||||||
// pub management: ManagementProtocol,
|
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 {
|
impl FolderAttributes {
|
||||||
@ -93,7 +112,7 @@ impl FolderAttributes {
|
|||||||
|
|
||||||
pub fn add_tag(&mut self, taggroup: impl Display, tagvalue: String) {
|
pub fn add_tag(&mut self, taggroup: impl Display, tagvalue: String) {
|
||||||
self.tags
|
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 {
|
pub fn with_tag(mut self, taggroup: impl Display, tagvalue: String) -> Self {
|
||||||
self.add_tag(taggroup, tagvalue);
|
self.add_tag(taggroup, tagvalue);
|
||||||
@ -109,7 +128,7 @@ pub struct MetaData {
|
|||||||
pub created_by: Option<String>,
|
pub created_by: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DomainExtention for FolderConfig {
|
impl DomainExtension for FolderConfig {
|
||||||
const DOMAIN_TYPE: super::DomainType = super::DomainType::FolderConfig;
|
const DOMAIN_TYPE: super::DomainType = super::DomainType::FolderConfig;
|
||||||
|
|
||||||
type CreationRequest = FolderCreationRequest;
|
type CreationRequest = FolderCreationRequest;
|
||||||
@ -227,10 +246,10 @@ impl FolderDeleteQuery {
|
|||||||
pub enum FolderDeleteMode {
|
pub enum FolderDeleteMode {
|
||||||
#[default]
|
#[default]
|
||||||
Recursive,
|
Recursive,
|
||||||
AbotyOnNonEmpty,
|
AbortOnNonEmpty,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BulkReadDomainExtention for FolderConfig {
|
impl BulkReadDomainExtension for FolderConfig {
|
||||||
type BulkReadQuery = FolderBulkReadQuery;
|
type BulkReadQuery = FolderBulkReadQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +265,7 @@ impl FolderBulkReadQuery {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BulkUpdateDomainExtention for FolderConfig {
|
impl BulkUpdateDomainExtension for FolderConfig {
|
||||||
type BulkUpdateRequest = FolderBulkUpdateRequest;
|
type BulkUpdateRequest = FolderBulkUpdateRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::api::folders::FolderAttributes;
|
use crate::api::folders::FolderAttributes;
|
||||||
use crate::api::{
|
use crate::api::{
|
||||||
BulkCreateDomainExtention, BulkDeleteDomainExtention, BulkReadDomainExtention,
|
BulkCreateDomainExtension, BulkDeleteDomainExtension, BulkReadDomainExtension,
|
||||||
BulkUpdateDomainExtention, DomainExtention,
|
BulkUpdateDomainExtension, DomainExtension,
|
||||||
};
|
};
|
||||||
use crate::{ApiClient, Client};
|
use crate::{ApiClient, Client};
|
||||||
|
|
||||||
@ -16,14 +18,32 @@ impl Client {
|
|||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
pub struct HostConfig {
|
pub struct HostConfig {
|
||||||
pub folder: String,
|
pub folder: String,
|
||||||
pub attributes: FolderAttributes,
|
pub attributes: HostAttributes,
|
||||||
pub effective_attributes: FolderAttributes,
|
pub effective_attributes: HostAttributes,
|
||||||
pub is_cluster: bool,
|
pub is_cluster: bool,
|
||||||
pub is_offline: bool,
|
pub is_offline: bool,
|
||||||
pub cluster_nodes: Option<Vec<String>>,
|
pub cluster_nodes: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DomainExtention for HostConfig {
|
|
||||||
|
#[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;
|
const DOMAIN_TYPE: super::DomainType = super::DomainType::HostConfig;
|
||||||
|
|
||||||
type CreationRequest = HostCreationRequest;
|
type CreationRequest = HostCreationRequest;
|
||||||
@ -35,7 +55,7 @@ impl DomainExtention for HostConfig {
|
|||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct HostCreationRequest {
|
pub struct HostCreationRequest {
|
||||||
pub hostname: String,
|
pub host_name: String,
|
||||||
pub folder: String,
|
pub folder: String,
|
||||||
pub attributes: FolderAttributes,
|
pub attributes: FolderAttributes,
|
||||||
}
|
}
|
||||||
@ -60,7 +80,7 @@ pub struct HostUpdateRequest {
|
|||||||
impl HostCreationRequest {
|
impl HostCreationRequest {
|
||||||
pub fn new(hostname: String, folder: String, attributes: FolderAttributes) -> Self {
|
pub fn new(hostname: String, folder: String, attributes: FolderAttributes) -> Self {
|
||||||
HostCreationRequest {
|
HostCreationRequest {
|
||||||
hostname,
|
host_name: hostname,
|
||||||
folder,
|
folder,
|
||||||
attributes,
|
attributes,
|
||||||
}
|
}
|
||||||
@ -105,14 +125,14 @@ impl HostUpdateRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BulkCreateDomainExtention for HostConfig {}
|
impl BulkCreateDomainExtension for HostConfig {}
|
||||||
impl BulkReadDomainExtention for HostConfig {
|
impl BulkReadDomainExtension for HostConfig {
|
||||||
type BulkReadQuery = HostBulkReadQuery;
|
type BulkReadQuery = HostBulkReadQuery;
|
||||||
}
|
}
|
||||||
impl BulkUpdateDomainExtention for HostConfig {
|
impl BulkUpdateDomainExtension for HostConfig {
|
||||||
type BulkUpdateRequest = HostBulkUpdateRequest;
|
type BulkUpdateRequest = HostBulkUpdateRequest;
|
||||||
}
|
}
|
||||||
impl BulkDeleteDomainExtention for HostConfig {}
|
impl BulkDeleteDomainExtension for HostConfig {}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize)]
|
#[derive(Debug, Default, Clone, Serialize)]
|
||||||
pub struct HostBulkReadQuery {
|
pub struct HostBulkReadQuery {
|
||||||
|
|||||||
@ -81,7 +81,7 @@ pub(crate) struct DomainCollection<E> {
|
|||||||
// pub extensions: Option<E>,
|
// pub extensions: Option<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DomainExtention: DeserializeOwned + Serialize {
|
pub trait DomainExtension: DeserializeOwned + Serialize {
|
||||||
const DOMAIN_TYPE: DomainType;
|
const DOMAIN_TYPE: DomainType;
|
||||||
|
|
||||||
type CreationRequest: Serialize;
|
type CreationRequest: Serialize;
|
||||||
@ -91,14 +91,14 @@ pub trait DomainExtention: DeserializeOwned + Serialize {
|
|||||||
type DeleteQuery: Serialize;
|
type DeleteQuery: Serialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// these are essentials tags for domain extentions to signal that bulk operations are possible
|
// these are essential tags for domain extensions to signal that bulk operations are possible
|
||||||
// not every extention supports bulk operations. and not all extentions that do support all of them
|
// not every extension supports bulk operations. and not all extensions that do support all of them
|
||||||
// and those that do tend to have a bit different types
|
// and those that do tend to have a bit different types
|
||||||
pub trait BulkCreateDomainExtention: DomainExtention {}
|
pub trait BulkCreateDomainExtension: DomainExtension {}
|
||||||
pub trait BulkReadDomainExtention: DomainExtention {
|
pub trait BulkReadDomainExtension: DomainExtension {
|
||||||
type BulkReadQuery: Serialize;
|
type BulkReadQuery: Serialize;
|
||||||
}
|
}
|
||||||
pub trait BulkUpdateDomainExtention: DomainExtention {
|
pub trait BulkUpdateDomainExtension: DomainExtension {
|
||||||
type BulkUpdateRequest: Serialize;
|
type BulkUpdateRequest: Serialize;
|
||||||
}
|
}
|
||||||
pub trait BulkDeleteDomainExtention: DomainExtention {}
|
pub trait BulkDeleteDomainExtension: DomainExtension {}
|
||||||
|
|||||||
@ -5,6 +5,6 @@ pub struct HostContactGroups {
|
|||||||
groups: Vec<String>,
|
groups: Vec<String>,
|
||||||
r#use: bool,
|
r#use: bool,
|
||||||
use_for_services: bool,
|
use_for_services: bool,
|
||||||
recuse_use: bool,
|
recurse_use: bool,
|
||||||
recuse_perms: bool,
|
recurse_perms: bool,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,8 +11,8 @@ use serde::de::DeserializeOwned;
|
|||||||
use tokio::sync::Semaphore;
|
use tokio::sync::Semaphore;
|
||||||
|
|
||||||
use crate::api::{
|
use crate::api::{
|
||||||
BulkCreateDomainExtention, BulkDeleteDomainExtention, BulkReadDomainExtention,
|
BulkCreateDomainExtension, BulkDeleteDomainExtension, BulkReadDomainExtension,
|
||||||
BulkUpdateDomainExtention, DomainCollection, DomainExtention, DomainObject, DomainType,
|
BulkUpdateDomainExtension, DomainCollection, DomainExtension, DomainObject, DomainType,
|
||||||
};
|
};
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
|
|
||||||
@ -26,8 +26,8 @@ pub(crate) struct InnerClient {
|
|||||||
|
|
||||||
#[derive(Default, PartialEq, Eq)]
|
#[derive(Default, PartialEq, Eq)]
|
||||||
enum SslStrategy {
|
enum SslStrategy {
|
||||||
NoSll,
|
NoSsl,
|
||||||
IngoreHostname,
|
IgnoreHostname,
|
||||||
IgnoreCertificate,
|
IgnoreCertificate,
|
||||||
#[default]
|
#[default]
|
||||||
Strict,
|
Strict,
|
||||||
@ -96,7 +96,7 @@ pub enum ClientBuildError {
|
|||||||
#[error("failed to build client: {0}")]
|
#[error("failed to build client: {0}")]
|
||||||
BuildClient(#[from] reqwest::Error),
|
BuildClient(#[from] reqwest::Error),
|
||||||
#[error(
|
#[error(
|
||||||
"invalid credentials. thise can only consist of visibly ASCII characters (ie. (32-127))"
|
"invalid credentials. these can only consist of visible ASCII characters (i.e. (32-127))"
|
||||||
)]
|
)]
|
||||||
InvalidCredentials(#[from] reqwest::header::InvalidHeaderValue),
|
InvalidCredentials(#[from] reqwest::header::InvalidHeaderValue),
|
||||||
}
|
}
|
||||||
@ -107,14 +107,14 @@ impl ClientBuilder<RequiresNothing> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn without_ssl(mut self) -> Self {
|
pub fn without_ssl(mut self) -> Self {
|
||||||
self.ssl = SslStrategy::NoSll;
|
self.ssl = SslStrategy::NoSsl;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn ignore_hostname_verification(mut self) -> Self {
|
pub fn ignore_hostname_verification(mut self) -> Self {
|
||||||
self.ssl = SslStrategy::IngoreHostname;
|
self.ssl = SslStrategy::IgnoreHostname;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
pub fn ignore_certificate_veritifcation(mut self) -> Self {
|
pub fn ignore_certificate_verification(mut self) -> Self {
|
||||||
self.ssl = SslStrategy::IgnoreCertificate;
|
self.ssl = SslStrategy::IgnoreCertificate;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -128,7 +128,7 @@ impl ClientBuilder<RequiresNothing> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn protocol(&self) -> &str {
|
fn protocol(&self) -> &str {
|
||||||
if self.ssl == SslStrategy::NoSll {
|
if self.ssl == SslStrategy::NoSsl {
|
||||||
"http"
|
"http"
|
||||||
} else {
|
} else {
|
||||||
"https"
|
"https"
|
||||||
@ -137,7 +137,7 @@ impl ClientBuilder<RequiresNothing> {
|
|||||||
fn port(&self) -> u16 {
|
fn port(&self) -> u16 {
|
||||||
if self.port != 0 {
|
if self.port != 0 {
|
||||||
self.port
|
self.port
|
||||||
} else if self.ssl == SslStrategy::NoSll {
|
} else if self.ssl == SslStrategy::NoSsl {
|
||||||
80
|
80
|
||||||
} else {
|
} else {
|
||||||
443
|
443
|
||||||
@ -165,7 +165,7 @@ impl ClientBuilder<RequiresNothing> {
|
|||||||
let mut builder = reqwest::ClientBuilder::new()
|
let mut builder = reqwest::ClientBuilder::new()
|
||||||
.default_headers(headers)
|
.default_headers(headers)
|
||||||
.danger_accept_invalid_certs(self.ssl == SslStrategy::IgnoreCertificate)
|
.danger_accept_invalid_certs(self.ssl == SslStrategy::IgnoreCertificate)
|
||||||
.danger_accept_invalid_hostnames(self.ssl == SslStrategy::IngoreHostname);
|
.danger_accept_invalid_hostnames(self.ssl == SslStrategy::IgnoreHostname);
|
||||||
|
|
||||||
if let Some(sock) = self.resolve {
|
if let Some(sock) = self.resolve {
|
||||||
builder = builder.resolve(&self.hostname, sock);
|
builder = builder.resolve(&self.hostname, sock);
|
||||||
@ -181,7 +181,7 @@ impl ClientBuilder<RequiresNothing> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// checkmk api struggles with more than 10 requests at a time
|
// checkmk api struggles with more than 10 requests at a time
|
||||||
// not sure if this has been inproved since 2.2
|
// not sure if this has been improved since 2.2
|
||||||
let semaphore = Semaphore::new(10);
|
let semaphore = Semaphore::new(10);
|
||||||
|
|
||||||
Ok(Client(Arc::new(InnerClient {
|
Ok(Client(Arc::new(InnerClient {
|
||||||
@ -282,7 +282,7 @@ impl InnerClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn create_domain_object<E: DomainExtention>(
|
pub(crate) async fn create_domain_object<E: DomainExtension>(
|
||||||
&self,
|
&self,
|
||||||
body: &E::CreationRequest,
|
body: &E::CreationRequest,
|
||||||
query: &E::CreationQuery,
|
query: &E::CreationQuery,
|
||||||
@ -297,7 +297,7 @@ impl InnerClient {
|
|||||||
|
|
||||||
self.invoke_api(request).await
|
self.invoke_api(request).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn read_domain_object<E: DomainExtention>(
|
pub(crate) async fn read_domain_object<E: DomainExtension>(
|
||||||
&self,
|
&self,
|
||||||
id: impl Display,
|
id: impl Display,
|
||||||
query: &E::ReadQuery,
|
query: &E::ReadQuery,
|
||||||
@ -311,7 +311,7 @@ impl InnerClient {
|
|||||||
|
|
||||||
self.query_api(request).await
|
self.query_api(request).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn update_domain_object<E: DomainExtention>(
|
pub(crate) async fn update_domain_object<E: DomainExtension>(
|
||||||
&self,
|
&self,
|
||||||
id: impl Display,
|
id: impl Display,
|
||||||
request: &E::UpdateRequest,
|
request: &E::UpdateRequest,
|
||||||
@ -328,7 +328,7 @@ impl InnerClient {
|
|||||||
|
|
||||||
self.invoke_api(request).await
|
self.invoke_api(request).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn delete_domain_object<E: DomainExtention>(
|
pub(crate) async fn delete_domain_object<E: DomainExtension>(
|
||||||
&self,
|
&self,
|
||||||
id: impl Display,
|
id: impl Display,
|
||||||
query: &E::DeleteQuery,
|
query: &E::DeleteQuery,
|
||||||
@ -343,13 +343,13 @@ impl InnerClient {
|
|||||||
self.invoke_api(request).await
|
self.invoke_api(request).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn bulk_create_domain_objects<E: BulkCreateDomainExtention>(
|
pub(crate) async fn bulk_create_domain_objects<E: BulkCreateDomainExtension>(
|
||||||
&self,
|
&self,
|
||||||
entries: &[E::CreationRequest],
|
entries: &[E::CreationRequest],
|
||||||
query: &E::CreationQuery,
|
query: &E::CreationQuery,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Request<'a, D: BulkCreateDomainExtention> {
|
struct Request<'a, D: BulkCreateDomainExtension> {
|
||||||
entries: &'a [D::CreationRequest],
|
entries: &'a [D::CreationRequest],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +363,7 @@ impl InnerClient {
|
|||||||
|
|
||||||
self.invoke_api(request).await
|
self.invoke_api(request).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn bulk_read_domain_objects<E: BulkReadDomainExtention>(
|
pub(crate) async fn bulk_read_domain_objects<E: BulkReadDomainExtension>(
|
||||||
&self,
|
&self,
|
||||||
query: &E::BulkReadQuery,
|
query: &E::BulkReadQuery,
|
||||||
) -> Result<Vec<DomainObject<E>>> {
|
) -> Result<Vec<DomainObject<E>>> {
|
||||||
@ -377,12 +377,12 @@ impl InnerClient {
|
|||||||
let response: DomainCollection<E> = self.query_api(request).await?;
|
let response: DomainCollection<E> = self.query_api(request).await?;
|
||||||
Ok(response.value)
|
Ok(response.value)
|
||||||
}
|
}
|
||||||
pub(crate) async fn bulk_update_domain_objects<E: BulkUpdateDomainExtention>(
|
pub(crate) async fn bulk_update_domain_objects<E: BulkUpdateDomainExtension>(
|
||||||
&self,
|
&self,
|
||||||
entries: &[E::BulkUpdateRequest],
|
entries: &[E::BulkUpdateRequest],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Request<'a, D: BulkUpdateDomainExtention> {
|
struct Request<'a, D: BulkUpdateDomainExtension> {
|
||||||
entries: &'a [D::BulkUpdateRequest],
|
entries: &'a [D::BulkUpdateRequest],
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,7 +395,7 @@ impl InnerClient {
|
|||||||
|
|
||||||
self.invoke_api(request).await
|
self.invoke_api(request).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn bulk_delete_domain_objects<E: BulkDeleteDomainExtention>(
|
pub(crate) async fn bulk_delete_domain_objects<E: BulkDeleteDomainExtension>(
|
||||||
&self,
|
&self,
|
||||||
entries: &[String],
|
entries: &[String],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
@ -433,12 +433,12 @@ impl Display for BulkAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ApiClient<D: DomainExtention> {
|
pub struct ApiClient<D: DomainExtension> {
|
||||||
pub(crate) inner: Arc<InnerClient>,
|
pub(crate) inner: Arc<InnerClient>,
|
||||||
_marker: PhantomData<D>,
|
_marker: PhantomData<D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: DomainExtention> From<&Client> for ApiClient<D> {
|
impl<D: DomainExtension> From<&Client> for ApiClient<D> {
|
||||||
fn from(value: &Client) -> Self {
|
fn from(value: &Client) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: value.0.clone(),
|
inner: value.0.clone(),
|
||||||
@ -447,7 +447,7 @@ impl<D: DomainExtention> From<&Client> for ApiClient<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: DomainExtention> ApiClient<D> {
|
impl<D: DomainExtension> ApiClient<D> {
|
||||||
pub async fn create(
|
pub async fn create(
|
||||||
&self,
|
&self,
|
||||||
request: &D::CreationRequest,
|
request: &D::CreationRequest,
|
||||||
@ -469,7 +469,7 @@ impl<D: DomainExtention> ApiClient<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: BulkCreateDomainExtention> ApiClient<D> {
|
impl<D: BulkCreateDomainExtension> ApiClient<D> {
|
||||||
pub async fn bulk_create(
|
pub async fn bulk_create(
|
||||||
&self,
|
&self,
|
||||||
request: &[D::CreationRequest],
|
request: &[D::CreationRequest],
|
||||||
@ -481,7 +481,7 @@ impl<D: BulkCreateDomainExtention> ApiClient<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: BulkReadDomainExtention> ApiClient<D> {
|
impl<D: BulkReadDomainExtension> ApiClient<D> {
|
||||||
pub async fn bulk_read(&self, query: &D::BulkReadQuery) -> 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 objs = self.inner.bulk_read_domain_objects::<D>(query).await?;
|
||||||
let exts = objs.into_iter().map(|obj| obj.extensions).collect();
|
let exts = objs.into_iter().map(|obj| obj.extensions).collect();
|
||||||
@ -489,13 +489,13 @@ impl<D: BulkReadDomainExtention> ApiClient<D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: BulkUpdateDomainExtention> ApiClient<D> {
|
impl<D: BulkUpdateDomainExtension> ApiClient<D> {
|
||||||
pub async fn bulk_update(&self, entries: &[D::BulkUpdateRequest]) -> Result<()> {
|
pub async fn bulk_update(&self, entries: &[D::BulkUpdateRequest]) -> Result<()> {
|
||||||
self.inner.bulk_update_domain_objects::<D>(entries).await
|
self.inner.bulk_update_domain_objects::<D>(entries).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D: BulkDeleteDomainExtention> ApiClient<D> {
|
impl<D: BulkDeleteDomainExtension> ApiClient<D> {
|
||||||
pub async fn bulk_delete(&self, ids: &[String]) -> Result<()> {
|
pub async fn bulk_delete(&self, ids: &[String]) -> Result<()> {
|
||||||
self.inner.bulk_delete_domain_objects::<D>(ids).await
|
self.inner.bulk_delete_domain_objects::<D>(ids).await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,14 +15,14 @@ pub enum Error {
|
|||||||
#[error(
|
#[error(
|
||||||
"Failed to send request: {}: {}", .0,
|
"Failed to send request: {}: {}", .0,
|
||||||
.0.cause().map(|e| e.to_string())
|
.0.cause().map(|e| e.to_string())
|
||||||
.unwrap_or_else(|| "Uknown Cause".to_string())
|
.unwrap_or_else(|| "Unknown Cause".to_string())
|
||||||
)]
|
)]
|
||||||
SendRequest(#[source] reqwest::Error),
|
SendRequest(#[source] reqwest::Error),
|
||||||
#[error("Failed to receive response-body: {0}")]
|
#[error("Failed to receive response-body: {0}")]
|
||||||
ReceiveBody(#[source] reqwest::Error),
|
ReceiveBody(#[source] reqwest::Error),
|
||||||
#[error("Failed to deserialize response: {0}")]
|
#[error("Failed to deserialize response: {0}")]
|
||||||
DeserializeResponse(#[source] serde_json::Error),
|
DeserializeResponse(#[source] serde_json::Error),
|
||||||
#[error("Recieved an error from checkmk ({}): {}", .0.status, .0.detail)]
|
#[error("Received an error from checkmk ({}): {}", .0.status, .0.detail)]
|
||||||
CheckmkError(#[source] CheckmkError),
|
CheckmkError(#[source] CheckmkError),
|
||||||
|
|
||||||
#[error("Checkmk site has not yet started. log in as site user and execute 'omd start'")]
|
#[error("Checkmk site has not yet started. log in as site user and execute 'omd start'")]
|
||||||
|
|||||||
65
src/main.rs
65
src/main.rs
@ -24,6 +24,7 @@ async fn main() -> Result<()> {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
test_folders(client.clone()).await?;
|
test_folders(client.clone()).await?;
|
||||||
|
test_hosts(client.clone()).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -48,11 +49,13 @@ async fn test_folders(client: Client) -> Result<()> {
|
|||||||
.create(&creq, &())
|
.create(&creq, &())
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to create folder: {e}"))?;
|
.inspect_err(|e| error!("failed to create folder: {e}"))?;
|
||||||
|
|
||||||
let folder = folderapi
|
let folder = folderapi
|
||||||
.read(TESTDIRQRY, &())
|
.read(TESTDIRQRY, &())
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to read folder: {e}"))?;
|
.inspect_err(|e| error!("failed to read folder: {e}"))?;
|
||||||
info!("folder config on site: {folder:?}");
|
info!("folder config on site: {folder:?}");
|
||||||
|
|
||||||
info!("updating folder");
|
info!("updating folder");
|
||||||
folderapi
|
folderapi
|
||||||
.update(TESTDIRQRY, &ureq1)
|
.update(TESTDIRQRY, &ureq1)
|
||||||
@ -64,6 +67,7 @@ async fn test_folders(client: Client) -> Result<()> {
|
|||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to read all folders: {e}"));
|
.inspect_err(|e| error!("failed to read all folders: {e}"));
|
||||||
info!("folder config on site: {folders:?}");
|
info!("folder config on site: {folders:?}");
|
||||||
|
|
||||||
folderapi
|
folderapi
|
||||||
.bulk_update(&[FolderBulkUpdateRequest::new(TESTDIRQRY.to_string(), ureq2)])
|
.bulk_update(&[FolderBulkUpdateRequest::new(TESTDIRQRY.to_string(), ureq2)])
|
||||||
.await
|
.await
|
||||||
@ -77,3 +81,64 @@ async fn test_folders(client: Client) -> Result<()> {
|
|||||||
|
|
||||||
Ok(())
|
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(())
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user