Compare commits
No commits in common. "f8a336429a0ea4482a0ee9e2c2842ec24dd128c9" and "71b1d3411d4b2b0a74b707337a777a3aaa6b8ab4" have entirely different histories.
f8a336429a
...
71b1d3411d
@ -4,8 +4,8 @@ use chrono::{DateTime, Utc};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::api::{DomainCollection, DomainExtension, DomainObject, domain_client, domain_read};
|
|
||||||
use crate::{ApiClient, Client, Result};
|
use crate::{ApiClient, Client, Result};
|
||||||
|
use crate::api::{DomainCollection, DomainExtension, DomainObject, domain_client, domain_read};
|
||||||
|
|
||||||
domain_client!(ActivationStatus, activation_api);
|
domain_client!(ActivationStatus, activation_api);
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ pub struct ActivationStatus {
|
|||||||
time_started: DateTime<Utc>,
|
time_started: DateTime<Utc>,
|
||||||
changes: Vec<PendingChange>,
|
changes: Vec<PendingChange>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
status_per_site: Vec<SiteStatus>,
|
status_per_site: Vec<SiteStatus>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DomainExtension for ActivationStatus {
|
impl DomainExtension for ActivationStatus {
|
||||||
@ -44,7 +44,7 @@ pub struct SiteStatus {
|
|||||||
status_text: String,
|
status_text: String,
|
||||||
status_details: String,
|
status_details: String,
|
||||||
start_time: DateTime<Utc>,
|
start_time: DateTime<Utc>,
|
||||||
end_time: DateTime<Utc>,
|
end_time: DateTime<Utc>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -57,7 +57,7 @@ pub enum ChangePhase {
|
|||||||
Sync,
|
Sync,
|
||||||
Activate,
|
Activate,
|
||||||
Finishing,
|
Finishing,
|
||||||
Done,
|
Done
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -66,7 +66,7 @@ pub enum ChangePhase {
|
|||||||
pub enum ChangeState {
|
pub enum ChangeState {
|
||||||
Success,
|
Success,
|
||||||
Error,
|
Error,
|
||||||
Warning,
|
Warning
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
@ -74,7 +74,7 @@ pub enum ChangeState {
|
|||||||
pub struct ActivateChangeRequest {
|
pub struct ActivateChangeRequest {
|
||||||
redirect: bool,
|
redirect: bool,
|
||||||
sites: Vec<String>,
|
sites: Vec<String>,
|
||||||
force_foreign_changes: bool,
|
force_foreign_changes: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
@ -82,7 +82,7 @@ pub struct ActivateChangeRequest {
|
|||||||
pub struct ActivationOptions {
|
pub struct ActivationOptions {
|
||||||
redirect: bool,
|
redirect: bool,
|
||||||
sites: Vec<String>,
|
sites: Vec<String>,
|
||||||
force_foreign_changes: bool,
|
force_foreign_changes: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActivationOptions {
|
impl ActivationOptions {
|
||||||
@ -120,38 +120,40 @@ impl ActivationOptions {
|
|||||||
domain_read!(ActivationStatus);
|
domain_read!(ActivationStatus);
|
||||||
|
|
||||||
impl ApiClient<ActivationStatus> {
|
impl ApiClient<ActivationStatus> {
|
||||||
pub async fn activate_pending_changes(&self, options: &ActivationOptions) -> Result<String> {
|
pub async fn activate_pending_changes(
|
||||||
|
&self,
|
||||||
|
options: &ActivationOptions
|
||||||
|
) -> Result<String> {
|
||||||
let etag = {
|
let etag = {
|
||||||
let url = format!("{}/pending_changes", self.collection_root());
|
let url = format!("{}/pending_changes", self.collection_root());
|
||||||
self.inner.get_etag(&url).await
|
self.inner.get_etag(&url).await
|
||||||
}?;
|
}?;
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/domain-types/{}/actions/activate-changes/invoke",
|
"{}/domain-types/{}/actions/activate-changes/invoke",
|
||||||
self.inner.url,
|
self.inner.url, ActivationStatus::DOMAIN_TYPE
|
||||||
ActivationStatus::DOMAIN_TYPE
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let request = self
|
let request = self.inner.http
|
||||||
.inner
|
|
||||||
.http
|
|
||||||
.post(url)
|
.post(url)
|
||||||
.json(&options)
|
.json(&options)
|
||||||
.header(reqwest::header::IF_MATCH, etag)
|
.header(reqwest::header::IF_MATCH, etag)
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let response: DomainObject<ActivationStatus> = self.inner.query_api(request).await?;
|
let response: DomainObject<ActivationStatus> =
|
||||||
|
self.inner.query_api(request).await?;
|
||||||
Ok(response.id)
|
Ok(response.id)
|
||||||
}
|
}
|
||||||
pub async fn await_completion(&self, activation_id: impl Display) -> Result<()> {
|
pub async fn await_completion(&self, activation_id: impl Display) -> Result<()> {
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}/objects/{}/{}/actions/wait-for-completion/invoke",
|
"{}/objects/{}/{}/actions/wait-for-completion/invoke",
|
||||||
self.inner.url,
|
self.inner.url, ActivationStatus::DOMAIN_TYPE, activation_id
|
||||||
ActivationStatus::DOMAIN_TYPE,
|
|
||||||
activation_id
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let request = self.inner.http.get(url).build().unwrap();
|
let request = self.inner.http
|
||||||
|
.get(url)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.inner.invoke_api(request).await
|
self.inner.invoke_api(request).await
|
||||||
}
|
}
|
||||||
@ -160,14 +162,16 @@ impl ApiClient<ActivationStatus> {
|
|||||||
fn collection_root(&self) -> String {
|
fn collection_root(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{}/domain-types/{}/collections",
|
"{}/domain-types/{}/collections",
|
||||||
self.inner.url,
|
self.inner.url, ActivationStatus::DOMAIN_TYPE
|
||||||
ActivationStatus::DOMAIN_TYPE
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
pub async fn read_running_activations(&self) -> Result<Vec<ActivationStatus>> {
|
pub async fn read_running_activations(&self) -> Result<Vec<ActivationStatus>> {
|
||||||
let url = format!("{}/running", self.collection_root());
|
let url = format!("{}/running", self.collection_root());
|
||||||
|
|
||||||
let request = self.inner.http.get(url).build().unwrap();
|
let request = self.inner.http
|
||||||
|
.get(url)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let collection: DomainCollection<_> = self.inner.query_api(request).await?;
|
let collection: DomainCollection<_> = self.inner.query_api(request).await?;
|
||||||
Ok(collection.into())
|
Ok(collection.into())
|
||||||
@ -175,11 +179,14 @@ impl ApiClient<ActivationStatus> {
|
|||||||
pub async fn read_pending_changes(&self) -> Result<Vec<PendingChange>> {
|
pub async fn read_pending_changes(&self) -> Result<Vec<PendingChange>> {
|
||||||
let url = format!("{}/pending_changes", self.collection_root());
|
let url = format!("{}/pending_changes", self.collection_root());
|
||||||
|
|
||||||
let request = self.inner.http.get(url).build().unwrap();
|
let request = self.inner.http
|
||||||
|
.get(url)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct ChangeCollection {
|
struct ChangeCollection {
|
||||||
value: Vec<PendingChange>,
|
value: Vec<PendingChange>
|
||||||
}
|
}
|
||||||
|
|
||||||
let collection: ChangeCollection = self.inner.query_api(request).await?;
|
let collection: ChangeCollection = self.inner.query_api(request).await?;
|
||||||
|
|||||||
@ -8,10 +8,9 @@ use serde_json::Value;
|
|||||||
#[cfg(feature = "schemars")]
|
#[cfg(feature = "schemars")]
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
use crate::api::{
|
use crate::api::rules::contactgroups::HostContactGroups;
|
||||||
DomainExtension, domain_bulk_read, domain_bulk_update, domain_client, domain_create,
|
use crate::api::rules::snmp::SnmpCommunity;
|
||||||
domain_delete, domain_read, domain_update,
|
use crate::api::{DomainExtension, domain_bulk_read, domain_bulk_update, domain_client, domain_create, domain_delete, domain_read, domain_update};
|
||||||
};
|
|
||||||
use crate::{ApiClient, Client, Result};
|
use crate::{ApiClient, Client, Result};
|
||||||
|
|
||||||
pub const ROOT_FOLDER: &str = "/";
|
pub const ROOT_FOLDER: &str = "/";
|
||||||
@ -25,7 +24,6 @@ pub struct FolderConfig {
|
|||||||
pub attributes: FolderAttributes,
|
pub attributes: FolderAttributes,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
pub struct FolderAttributes {
|
pub struct FolderAttributes {
|
||||||
@ -48,6 +46,7 @@ pub struct FolderAttributes {
|
|||||||
#[serde(default, flatten, skip_serializing_if = "HashMap::is_empty")]
|
#[serde(default, flatten, skip_serializing_if = "HashMap::is_empty")]
|
||||||
pub tags: HashMap<String, String>,
|
pub tags: HashMap<String, String>,
|
||||||
|
|
||||||
|
|
||||||
// these fields are used to prevent tags from taking them up
|
// these fields are used to prevent tags from taking them up
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
management_snmp_community: Option<SnmpCommunity>,
|
management_snmp_community: Option<SnmpCommunity>,
|
||||||
@ -113,7 +112,8 @@ 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.insert(format!("tag_{taggroup}"), tagvalue);
|
self.tags
|
||||||
|
.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);
|
||||||
@ -130,89 +130,6 @@ pub struct MetaData {
|
|||||||
pub created_by: Option<String>,
|
pub created_by: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub enum SnmpV3AuthProtocol {
|
|
||||||
#[serde(rename = "MD5-96")]
|
|
||||||
Md5,
|
|
||||||
#[serde(rename = "SHA-1-96")]
|
|
||||||
Sha96,
|
|
||||||
#[serde(rename = "SHA-2-224")]
|
|
||||||
Sha224,
|
|
||||||
#[serde(rename = "SHA-2-256")]
|
|
||||||
Sha256,
|
|
||||||
#[serde(rename = "SHA-2-384")]
|
|
||||||
Sha384,
|
|
||||||
#[serde(rename = "SHA-2-512")]
|
|
||||||
Sha512,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct SnmpV3Auth {
|
|
||||||
pub auth_protocol: SnmpV3AuthProtocol,
|
|
||||||
pub security_name: String,
|
|
||||||
pub auth_password: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub enum SnmpV3PrivProtocol {
|
|
||||||
#[serde(rename = "CBC-DES")]
|
|
||||||
Des,
|
|
||||||
#[serde(rename = "3DES-EDE")]
|
|
||||||
Des3,
|
|
||||||
#[serde(rename = "AES-128")]
|
|
||||||
Aes128,
|
|
||||||
#[serde(rename = "AES-192")]
|
|
||||||
Aes192,
|
|
||||||
#[serde(rename = "AES-256")]
|
|
||||||
Aes256,
|
|
||||||
#[serde(rename = "AES-192-Blumenthal")]
|
|
||||||
Aes192Blumenthal,
|
|
||||||
#[serde(rename = "AES-256-Blumenthal")]
|
|
||||||
Aes256Blumenthal,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct SnmpV3Priv {
|
|
||||||
pub privacy_protocol: SnmpV3PrivProtocol,
|
|
||||||
pub privacy_password: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
#[serde(tag = "type")]
|
|
||||||
pub enum SnmpCommunity {
|
|
||||||
V1V2Community {
|
|
||||||
community: String,
|
|
||||||
},
|
|
||||||
NoAuthNoPriv {
|
|
||||||
security_name: String,
|
|
||||||
},
|
|
||||||
AuthNoPriv {
|
|
||||||
#[serde(flatten)]
|
|
||||||
auth: SnmpV3Auth,
|
|
||||||
},
|
|
||||||
AuthPriv {
|
|
||||||
#[serde(flatten)]
|
|
||||||
authentication: SnmpV3Auth,
|
|
||||||
#[serde(flatten)]
|
|
||||||
privacy: SnmpV3Priv,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct HostContactGroups {
|
|
||||||
pub groups: Vec<String>,
|
|
||||||
pub r#use: bool,
|
|
||||||
pub use_for_services: bool,
|
|
||||||
pub recurse_use: bool,
|
|
||||||
pub recurse_perms: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DomainExtension for FolderConfig {
|
impl DomainExtension for FolderConfig {
|
||||||
const DOMAIN_TYPE: super::DomainType = super::DomainType::FolderConfig;
|
const DOMAIN_TYPE: super::DomainType = super::DomainType::FolderConfig;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,19 @@
|
|||||||
use core::ops::Deref;
|
use core::ops::Deref;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "schemars")]
|
#[cfg(feature = "schemars")]
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::api::{DomainCollection, DomainObject, DomainType, domain_client};
|
use crate::api::{
|
||||||
|
DomainCollection, DomainObject, DomainType, domain_client
|
||||||
|
};
|
||||||
use crate::{ApiClient, Client, Result};
|
use crate::{ApiClient, Client, Result};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
pub struct Group {
|
pub struct Group {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub alias: String,
|
pub alias: String
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Group {
|
impl Group {
|
||||||
@ -26,6 +28,7 @@ impl From<DomainObject<serde_json::Value>> for Group {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
macro_rules! domain_group {
|
macro_rules! domain_group {
|
||||||
($id:ident, $typ:expr, $func:ident) => {
|
($id:ident, $typ:expr, $func:ident) => {
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -58,13 +61,14 @@ macro_rules! domain_group {
|
|||||||
self.inner.create($typ, group, &()).await
|
self.inner.create($typ, group, &()).await
|
||||||
}
|
}
|
||||||
pub async fn read(&self, id: &str) -> Result<$id> {
|
pub async fn read(&self, id: &str) -> Result<$id> {
|
||||||
let obj: DomainObject<serde_json::Value> = self.inner.read($typ, id, &()).await?;
|
let obj: DomainObject<serde_json::Value> =
|
||||||
|
self.inner.read($typ, id, &()).await?;
|
||||||
Ok($id::from(obj))
|
Ok($id::from(obj))
|
||||||
}
|
}
|
||||||
pub async fn update(&self, id: &str, alias: &str) -> Result<()> {
|
pub async fn update(&self, id: &str, alias: &str) -> Result<()> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Body<'a> {
|
struct Body<'a> {
|
||||||
alias: &'a str,
|
alias: &'a str
|
||||||
}
|
}
|
||||||
|
|
||||||
self.inner.update($typ, id, &Body { alias }).await
|
self.inner.update($typ, id, &Body { alias }).await
|
||||||
@ -79,48 +83,45 @@ macro_rules! domain_group {
|
|||||||
pub async fn bulk_read(&self) -> Result<Vec<$id>> {
|
pub async fn bulk_read(&self) -> Result<Vec<$id>> {
|
||||||
let collection: DomainCollection<serde_json::Value> =
|
let collection: DomainCollection<serde_json::Value> =
|
||||||
self.inner.bulk_read($typ, &()).await?;
|
self.inner.bulk_read($typ, &()).await?;
|
||||||
let groups = collection.value.into_iter().map($id::from).collect();
|
let groups = collection.value
|
||||||
|
.into_iter()
|
||||||
|
.map($id::from)
|
||||||
|
.collect();
|
||||||
Ok(groups)
|
Ok(groups)
|
||||||
}
|
}
|
||||||
pub async fn bulk_update(&self, entries: &[Group]) -> Result<()> {
|
pub async fn bulk_update(&self, entries: &[Group]) -> Result<()> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct UpdateAttributes<'a> {
|
struct UpdateAttributes<'a> {
|
||||||
alias: &'a str,
|
alias: &'a str
|
||||||
}
|
}
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct UpdateRequest<'a> {
|
struct UpdateRequest<'a> {
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
attributes: UpdateAttributes<'a>,
|
attributes: UpdateAttributes<'a>
|
||||||
}
|
}
|
||||||
impl<'a> UpdateRequest<'a> {
|
impl <'a> UpdateRequest<'a> {
|
||||||
fn from(value: &'a Group) -> Self {
|
fn from(value: &'a Group) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name: value.name.as_str(),
|
name: value.name.as_str(),
|
||||||
attributes: UpdateAttributes {
|
attributes: UpdateAttributes {
|
||||||
alias: value.alias.as_str(),
|
alias: value.alias.as_str()
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries = entries.iter().map(UpdateRequest::from).collect::<Vec<_>>();
|
let entries = entries.iter()
|
||||||
|
.map(UpdateRequest::from)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
self.inner.bulk_update($typ, &entries).await
|
self.inner.bulk_update($typ, &entries).await
|
||||||
}
|
}
|
||||||
pub async fn bulk_delete(&self, entries: &[String]) -> Result<()> {
|
pub async fn bulk_delete(&self, entries: &[String]) -> Result<()> {
|
||||||
self.inner.bulk_delete($typ, entries).await
|
self.inner.bulk_delete($typ, entries).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
domain_group!(HostGroup, DomainType::HostGroupConfig, host_group_api);
|
domain_group!(HostGroup, DomainType::HostGroupConfig, host_group_api);
|
||||||
domain_group!(
|
domain_group!(ServiceGroup, DomainType::ServiceGroupConfig, service_group_api);
|
||||||
ServiceGroup,
|
domain_group!(ContactGroup, DomainType::ContactGroupConfig, contact_group_api);
|
||||||
DomainType::ServiceGroupConfig,
|
|
||||||
service_group_api
|
|
||||||
);
|
|
||||||
domain_group!(
|
|
||||||
ContactGroup,
|
|
||||||
DomainType::ContactGroupConfig,
|
|
||||||
contact_group_api
|
|
||||||
);
|
|
||||||
|
|||||||
@ -1,17 +1,17 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "schemars")]
|
#[cfg(feature = "schemars")]
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::api::folders::FolderAttributes;
|
use crate::api::folders::FolderAttributes;
|
||||||
use crate::api::{
|
use crate::api::{
|
||||||
DomainExtension, domain_bulk_create, domain_bulk_delete, domain_bulk_read, domain_bulk_update,
|
DomainExtension, domain_bulk_create, domain_bulk_delete, domain_bulk_read, domain_bulk_update, domain_client, domain_create, domain_delete, domain_read, domain_update
|
||||||
domain_client, domain_create, domain_delete, domain_read, domain_update,
|
|
||||||
};
|
};
|
||||||
use crate::{ApiClient, Client, Result};
|
use crate::{ApiClient, Client, Result};
|
||||||
|
|
||||||
|
|
||||||
domain_client!(HostConfig, host_api);
|
domain_client!(HostConfig, host_api);
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
@ -25,6 +25,7 @@ pub struct HostConfig {
|
|||||||
pub cluster_nodes: Option<Vec<String>>,
|
pub cluster_nodes: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
pub struct HostAttributes {
|
pub struct HostAttributes {
|
||||||
@ -40,7 +41,7 @@ pub struct HostAttributes {
|
|||||||
additional_ipv6addresses: Vec<Ipv6Addr>,
|
additional_ipv6addresses: Vec<Ipv6Addr>,
|
||||||
|
|
||||||
#[serde(flatten, default)]
|
#[serde(flatten, default)]
|
||||||
folder_attributes: FolderAttributes,
|
folder_attributes: FolderAttributes
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DomainExtension for HostConfig {
|
impl DomainExtension for HostConfig {
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
pub mod activations;
|
pub mod activations;
|
||||||
pub mod folders;
|
pub mod folders;
|
||||||
pub mod groups;
|
|
||||||
pub mod hosts;
|
pub mod hosts;
|
||||||
pub mod rules;
|
pub mod groups;
|
||||||
|
pub(crate) mod rules;
|
||||||
pub mod tags;
|
pub mod tags;
|
||||||
|
|
||||||
use std::fmt::{self, Display};
|
use std::fmt::{self, Display};
|
||||||
@ -23,9 +23,6 @@ pub enum DomainType {
|
|||||||
ServiceGroupConfig,
|
ServiceGroupConfig,
|
||||||
HostTagGroup,
|
HostTagGroup,
|
||||||
ActivationRun,
|
ActivationRun,
|
||||||
Ruleset,
|
|
||||||
Rule,
|
|
||||||
Dict,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for DomainType {
|
impl fmt::Display for DomainType {
|
||||||
@ -38,10 +35,7 @@ impl fmt::Display for DomainType {
|
|||||||
DomainType::HostGroupConfig => write!(f, "host_group_config"),
|
DomainType::HostGroupConfig => write!(f, "host_group_config"),
|
||||||
DomainType::ServiceGroupConfig => write!(f, "service_group_config"),
|
DomainType::ServiceGroupConfig => write!(f, "service_group_config"),
|
||||||
DomainType::HostTagGroup => write!(f, "host_tag_group"),
|
DomainType::HostTagGroup => write!(f, "host_tag_group"),
|
||||||
DomainType::ActivationRun => write!(f, "activation_run"),
|
DomainType::ActivationRun => write!(f, "activation_run")
|
||||||
DomainType::Ruleset => write!(f, "ruleset"),
|
|
||||||
DomainType::Rule => write!(f, "rule"),
|
|
||||||
DomainType::Dict => write!(f, "dict"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -97,9 +91,12 @@ pub(crate) struct DomainCollection<E> {
|
|||||||
// pub extensions: Option<E>,
|
// pub extensions: Option<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> From<DomainCollection<E>> for Vec<E> {
|
impl <E> From<DomainCollection<E>> for Vec<E> {
|
||||||
fn from(value: DomainCollection<E>) -> Self {
|
fn from(value: DomainCollection<E>) -> Self {
|
||||||
value.value.into_iter().map(|obj| obj.extensions).collect()
|
value.value
|
||||||
|
.into_iter()
|
||||||
|
.map(|obj| obj.extensions)
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,11 +105,15 @@ pub trait DomainExtension: DeserializeOwned + Serialize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl InnerClient {
|
impl InnerClient {
|
||||||
pub(crate) async fn create_domain_object<E, O, Q>(&self, object: &O, query: &Q) -> Result<()>
|
pub(crate) async fn create_domain_object<E, O, Q>(
|
||||||
|
&self,
|
||||||
|
object: &O,
|
||||||
|
query: &Q,
|
||||||
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
E: DomainExtension,
|
E: DomainExtension,
|
||||||
O: Serialize,
|
O: Serialize,
|
||||||
Q: Serialize,
|
Q: Serialize
|
||||||
{
|
{
|
||||||
self.create(E::DOMAIN_TYPE, object, query).await
|
self.create(E::DOMAIN_TYPE, object, query).await
|
||||||
}
|
}
|
||||||
@ -123,7 +124,7 @@ impl InnerClient {
|
|||||||
) -> Result<DomainObject<E>>
|
) -> Result<DomainObject<E>>
|
||||||
where
|
where
|
||||||
E: DomainExtension,
|
E: DomainExtension,
|
||||||
Q: Serialize,
|
Q: Serialize
|
||||||
{
|
{
|
||||||
self.read(E::DOMAIN_TYPE, id, query).await
|
self.read(E::DOMAIN_TYPE, id, query).await
|
||||||
}
|
}
|
||||||
@ -134,14 +135,18 @@ impl InnerClient {
|
|||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
E: DomainExtension,
|
E: DomainExtension,
|
||||||
O: Serialize,
|
O: Serialize
|
||||||
{
|
{
|
||||||
self.update(E::DOMAIN_TYPE, id, object).await
|
self.update(E::DOMAIN_TYPE, id, object).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn delete_domain_object<E, Q>(&self, id: impl Display, query: &Q) -> Result<()>
|
pub(crate) async fn delete_domain_object<E, Q>(
|
||||||
|
&self,
|
||||||
|
id: impl Display,
|
||||||
|
query: &Q,
|
||||||
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
E: DomainExtension,
|
E: DomainExtension,
|
||||||
Q: Serialize,
|
Q: Serialize
|
||||||
{
|
{
|
||||||
self.delete(E::DOMAIN_TYPE, id, query).await
|
self.delete(E::DOMAIN_TYPE, id, query).await
|
||||||
}
|
}
|
||||||
@ -154,7 +159,7 @@ impl InnerClient {
|
|||||||
where
|
where
|
||||||
E: DomainExtension,
|
E: DomainExtension,
|
||||||
O: Serialize,
|
O: Serialize,
|
||||||
Q: Serialize,
|
Q: Serialize
|
||||||
{
|
{
|
||||||
self.bulk_create(E::DOMAIN_TYPE, entries, query).await
|
self.bulk_create(E::DOMAIN_TYPE, entries, query).await
|
||||||
}
|
}
|
||||||
@ -164,25 +169,33 @@ impl InnerClient {
|
|||||||
) -> Result<DomainCollection<E>>
|
) -> Result<DomainCollection<E>>
|
||||||
where
|
where
|
||||||
E: DomainExtension,
|
E: DomainExtension,
|
||||||
Q: Serialize,
|
Q: Serialize
|
||||||
{
|
{
|
||||||
self.bulk_read(E::DOMAIN_TYPE, query).await
|
self.bulk_read(E::DOMAIN_TYPE, query).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn bulk_update_domain_objects<E, O>(&self, entries: &[O]) -> Result<()>
|
pub(crate) async fn bulk_update_domain_objects<E, O>(
|
||||||
|
&self,
|
||||||
|
entries: &[O],
|
||||||
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
E: DomainExtension,
|
E: DomainExtension,
|
||||||
O: Serialize,
|
O: Serialize
|
||||||
{
|
{
|
||||||
self.bulk_update(E::DOMAIN_TYPE, entries).await
|
self.bulk_update(E::DOMAIN_TYPE, entries).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn bulk_delete_domain_objects<E>(&self, entries: &[String]) -> Result<()>
|
pub(crate) async fn bulk_delete_domain_objects<E>(
|
||||||
|
&self,
|
||||||
|
entries: &[String],
|
||||||
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
E: DomainExtension,
|
E: DomainExtension
|
||||||
{
|
{
|
||||||
self.bulk_delete(E::DOMAIN_TYPE, entries).await
|
self.bulk_delete(E::DOMAIN_TYPE, entries).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
macro_rules! domain_client {
|
macro_rules! domain_client {
|
||||||
($id:ident, $func:ident) => {
|
($id:ident, $func:ident) => {
|
||||||
impl Client {
|
impl Client {
|
||||||
@ -198,7 +211,7 @@ macro_rules! domain_client {
|
|||||||
Self::new(value)
|
Self::new(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
pub(super) use domain_client;
|
pub(super) use domain_client;
|
||||||
|
|
||||||
@ -206,18 +219,14 @@ macro_rules! domain_create {
|
|||||||
($id:ident, $object:ident) => {
|
($id:ident, $object:ident) => {
|
||||||
impl ApiClient<$id> {
|
impl ApiClient<$id> {
|
||||||
pub async fn create(&self, object: &$object) -> Result<()> {
|
pub async fn create(&self, object: &$object) -> Result<()> {
|
||||||
self.inner
|
self.inner.create_domain_object::<$id, _, _>(object, &()).await
|
||||||
.create_domain_object::<$id, _, _>(object, &())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($id:ident, $object:ident, $qry:ident) => {
|
($id:ident, $object:ident, $qry:ident) => {
|
||||||
impl ApiClient<$id> {
|
impl ApiClient<$id> {
|
||||||
pub async fn create(&self, object: &$object, query: &$qry) -> Result<()> {
|
pub async fn create(&self, object: &$object, query: &$qry) -> Result<()> {
|
||||||
self.inner
|
self.inner.create_domain_object::<$id, _, _>(object, query).await
|
||||||
.create_domain_object::<$id, _, _>(object, query)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -228,9 +237,7 @@ macro_rules! domain_read {
|
|||||||
($id:ident) => {
|
($id:ident) => {
|
||||||
impl ApiClient<$id> {
|
impl ApiClient<$id> {
|
||||||
pub async fn read(&self, id: impl Display) -> Result<$id> {
|
pub async fn read(&self, id: impl Display) -> Result<$id> {
|
||||||
self.inner
|
self.inner.read_domain_object::<$id, _>(id, &()).await
|
||||||
.read_domain_object::<$id, _>(id, &())
|
|
||||||
.await
|
|
||||||
.map(|obj| obj.extensions)
|
.map(|obj| obj.extensions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -238,9 +245,7 @@ macro_rules! domain_read {
|
|||||||
($id:ident, $qry:ident) => {
|
($id:ident, $qry:ident) => {
|
||||||
impl ApiClient<$id> {
|
impl ApiClient<$id> {
|
||||||
pub async fn read(&self, id: impl Display, query: &$qry) -> Result<$id> {
|
pub async fn read(&self, id: impl Display, query: &$qry) -> Result<$id> {
|
||||||
self.inner
|
self.inner.read_domain_object::<$id, _>(id, &query).await
|
||||||
.read_domain_object::<$id, _>(id, &query)
|
|
||||||
.await
|
|
||||||
.map(|obj| obj.extensions)
|
.map(|obj| obj.extensions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -281,18 +286,14 @@ macro_rules! domain_bulk_create {
|
|||||||
($id:ident, $object:ident) => {
|
($id:ident, $object:ident) => {
|
||||||
impl ApiClient<$id> {
|
impl ApiClient<$id> {
|
||||||
pub async fn bulk_create(&self, entries: &[$object]) -> Result<()> {
|
pub async fn bulk_create(&self, entries: &[$object]) -> Result<()> {
|
||||||
self.inner
|
self.inner.bulk_create_domain_objects::<$id, _, _>(entries, &()).await
|
||||||
.bulk_create_domain_objects::<$id, _, _>(entries, &())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($id:ident, $object:ident, $qry:ident) => {
|
($id:ident, $object:ident, $qry:ident) => {
|
||||||
impl ApiClient<$id> {
|
impl ApiClient<$id> {
|
||||||
pub async fn bulk_create(&self, entries: &[$object], query: &$qry) -> Result<()> {
|
pub async fn bulk_create(&self, entries: &[$object], query: &$qry) -> Result<()> {
|
||||||
self.inner
|
self.inner.bulk_create_domain_objects::<$id, _, _>(entries, query).await
|
||||||
.bulk_create_domain_objects::<$id, _, _>(entries, query)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -311,10 +312,7 @@ macro_rules! domain_bulk_read {
|
|||||||
($id:ident, $qry:ident) => {
|
($id:ident, $qry:ident) => {
|
||||||
impl ApiClient<$id> {
|
impl ApiClient<$id> {
|
||||||
pub async fn bulk_read(&self, query: &$qry) -> Result<Vec<$id>> {
|
pub async fn bulk_read(&self, query: &$qry) -> Result<Vec<$id>> {
|
||||||
let collection = self
|
let collection = self.inner.bulk_read_domain_objects::<$id, _>(&query).await?;
|
||||||
.inner
|
|
||||||
.bulk_read_domain_objects::<$id, _>(&query)
|
|
||||||
.await?;
|
|
||||||
Ok(collection.into())
|
Ok(collection.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -326,9 +324,7 @@ macro_rules! domain_bulk_update {
|
|||||||
($id:ident, $object:ident) => {
|
($id:ident, $object:ident) => {
|
||||||
impl ApiClient<$id> {
|
impl ApiClient<$id> {
|
||||||
pub async fn bulk_update(&self, entries: &[$object]) -> Result<()> {
|
pub async fn bulk_update(&self, entries: &[$object]) -> Result<()> {
|
||||||
self.inner
|
self.inner.bulk_update_domain_objects::<$id, _>(entries).await
|
||||||
.bulk_update_domain_objects::<$id, _>(entries)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
695
src/api/rules.rs
695
src/api/rules.rs
@ -1,695 +0,0 @@
|
|||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
#[cfg(feature = "schemars")]
|
|
||||||
use schemars::JsonSchema;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::api::{
|
|
||||||
DomainExtension, DomainObject, domain_bulk_read, domain_client, domain_create, domain_delete,
|
|
||||||
domain_update,
|
|
||||||
};
|
|
||||||
use crate::{ApiClient, Client, Error, 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);
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct Rule {
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub folder_index: Option<usize>,
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub id: Option<Uuid>,
|
|
||||||
|
|
||||||
pub ruleset: String,
|
|
||||||
pub folder: String,
|
|
||||||
pub properties: RuleProperties,
|
|
||||||
pub value_raw: String,
|
|
||||||
pub conditions: RuleCondition,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DomainExtension for Rule {
|
|
||||||
const DOMAIN_TYPE: super::DomainType = super::DomainType::Rule;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Rule {
|
|
||||||
pub fn new(ruleset: String, folder: String) -> Self {
|
|
||||||
Self {
|
|
||||||
ruleset,
|
|
||||||
folder,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_ruleset(&mut self, ruleset: String) {
|
|
||||||
self.ruleset = ruleset;
|
|
||||||
}
|
|
||||||
pub fn with_ruleset(mut self, ruleset: String) -> Self {
|
|
||||||
self.set_ruleset(ruleset);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_folder(&mut self, folder: String) {
|
|
||||||
self.folder = folder;
|
|
||||||
}
|
|
||||||
pub fn with_folder(mut self, folder: String) -> Self {
|
|
||||||
self.set_folder(folder);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_properties(&mut self, properties: RuleProperties) {
|
|
||||||
self.properties = properties;
|
|
||||||
}
|
|
||||||
pub fn with_properties(mut self, properties: RuleProperties) -> Self {
|
|
||||||
self.set_properties(properties);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_value_raw(&mut self, value_raw: String) {
|
|
||||||
self.value_raw = value_raw;
|
|
||||||
}
|
|
||||||
pub fn with_value_raw(mut self, value_raw: String) -> Self {
|
|
||||||
self.set_value_raw(value_raw);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_conditions(&mut self, conditions: RuleCondition) {
|
|
||||||
self.conditions = conditions;
|
|
||||||
}
|
|
||||||
pub fn with_conditions(mut self, conditions: RuleCondition) -> Self {
|
|
||||||
self.set_conditions(conditions);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct RuleProperties {
|
|
||||||
pub description: String,
|
|
||||||
pub comment: String,
|
|
||||||
pub documentation_url: String,
|
|
||||||
pub disabled: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RuleProperties {
|
|
||||||
pub fn new(description: String) -> Self {
|
|
||||||
Self {
|
|
||||||
description,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_description(&mut self, description: String) {
|
|
||||||
self.description = description;
|
|
||||||
}
|
|
||||||
pub fn with_description(mut self, description: String) -> Self {
|
|
||||||
self.set_description(description);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_comment(&mut self, comment: String) {
|
|
||||||
self.comment = comment;
|
|
||||||
}
|
|
||||||
pub fn with_comment(mut self, comment: String) -> Self {
|
|
||||||
self.set_comment(comment);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_documentation_url(&mut self, url: String) {
|
|
||||||
self.documentation_url = url;
|
|
||||||
}
|
|
||||||
pub fn with_documentation_url(mut self, url: String) -> Self {
|
|
||||||
self.set_documentation_url(url);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_disabled(&mut self, disabled: bool) {
|
|
||||||
self.disabled = disabled;
|
|
||||||
}
|
|
||||||
pub fn with_disabled(mut self, disabled: bool) -> Self {
|
|
||||||
self.set_disabled(disabled);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: implement
|
|
||||||
pub trait RuleMatch {
|
|
||||||
fn matches(&self, other: Self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct RuleCondition {
|
|
||||||
pub host_name: Option<MatchCondition>,
|
|
||||||
pub host_tags: Vec<HostTagCondition>,
|
|
||||||
pub host_label_groups: Vec<LabelGroupCondition>,
|
|
||||||
pub service_label_groups: Vec<LabelGroupCondition>,
|
|
||||||
pub service_description: Option<MatchCondition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl RuleCondition {
|
|
||||||
/// Match hosts whose name is one of the given values.
|
|
||||||
pub fn match_hosts(&mut self, hosts: Vec<String>) {
|
|
||||||
self.host_name = Some(MatchCondition {
|
|
||||||
match_on: hosts,
|
|
||||||
operator: MatchOperator::OneOf,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn matching_hosts(mut self, hosts: Vec<String>) -> Self {
|
|
||||||
self.match_hosts(hosts);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exclude hosts whose name is one of the given values.
|
|
||||||
pub fn exclude_hosts(&mut self, hosts: Vec<String>) {
|
|
||||||
self.host_name = Some(MatchCondition {
|
|
||||||
match_on: hosts,
|
|
||||||
operator: MatchOperator::NoneOf,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn excluding_hosts(mut self, hosts: Vec<String>) -> Self {
|
|
||||||
self.exclude_hosts(hosts);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clear any host name condition.
|
|
||||||
pub fn clear_hosts(&mut self) {
|
|
||||||
self.host_name = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Match services whose description is one of the given values.
|
|
||||||
pub fn match_services(&mut self, services: Vec<String>) {
|
|
||||||
self.service_description = Some(MatchCondition {
|
|
||||||
match_on: services,
|
|
||||||
operator: MatchOperator::OneOf,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn matching_services(mut self, services: Vec<String>) -> Self {
|
|
||||||
self.match_services(services);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exclude services whose description is one of the given values.
|
|
||||||
pub fn exclude_services(&mut self, services: Vec<String>) {
|
|
||||||
self.service_description = Some(MatchCondition {
|
|
||||||
match_on: services,
|
|
||||||
operator: MatchOperator::NoneOf,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn excluding_services(mut self, services: Vec<String>) -> Self {
|
|
||||||
self.exclude_services(services);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Clear any service description condition.
|
|
||||||
pub fn clear_services(&mut self) {
|
|
||||||
self.service_description = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Require the host tag `key` to equal `value`.
|
|
||||||
pub fn require_host_tag(&mut self, key: String, value: String) {
|
|
||||||
self.host_tags.push(HostTagCondition {
|
|
||||||
key,
|
|
||||||
match_on: TagMatchOperator::Is(value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn with_host_tag(mut self, key: String, value: String) -> Self {
|
|
||||||
self.require_host_tag(key, value);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Require the host tag `key` to not equal `value`.
|
|
||||||
pub fn exclude_host_tag(&mut self, key: String, value: String) {
|
|
||||||
self.host_tags.push(HostTagCondition {
|
|
||||||
key,
|
|
||||||
match_on: TagMatchOperator::IsNot(value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn without_host_tag(mut self, key: String, value: String) -> Self {
|
|
||||||
self.exclude_host_tag(key, value);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Require the host tag `key` to be one of `values`.
|
|
||||||
pub fn require_any_host_tag(&mut self, key: String, values: Vec<String>) {
|
|
||||||
self.host_tags.push(HostTagCondition {
|
|
||||||
key,
|
|
||||||
match_on: TagMatchOperator::OneOff(values),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn with_any_host_tag(mut self, key: String, values: Vec<String>) -> Self {
|
|
||||||
self.require_any_host_tag(key, values);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Require the host tag `key` to be none of `values`.
|
|
||||||
pub fn exclude_any_host_tag(&mut self, key: String, values: Vec<String>) {
|
|
||||||
self.host_tags.push(HostTagCondition {
|
|
||||||
key,
|
|
||||||
match_on: TagMatchOperator::NoneOff(values),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn without_any_host_tag(mut self, key: String, values: Vec<String>) -> Self {
|
|
||||||
self.exclude_any_host_tag(key, values);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a host label group that must ALL match (AND).
|
|
||||||
pub fn require_host_labels(&mut self, labels: Vec<LabelCondition>) {
|
|
||||||
self.host_label_groups.push(LabelGroupCondition {
|
|
||||||
operator: LabelOperator::And,
|
|
||||||
label_group: labels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn with_host_labels(mut self, labels: Vec<LabelCondition>) -> Self {
|
|
||||||
self.require_host_labels(labels);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a host label group where ANY must match (OR).
|
|
||||||
pub fn require_any_host_label(&mut self, labels: Vec<LabelCondition>) {
|
|
||||||
self.host_label_groups.push(LabelGroupCondition {
|
|
||||||
operator: LabelOperator::Or,
|
|
||||||
label_group: labels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn with_any_host_label(mut self, labels: Vec<LabelCondition>) -> Self {
|
|
||||||
self.require_any_host_label(labels);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a host label group that must NOT match (NOT).
|
|
||||||
pub fn exclude_host_labels(&mut self, labels: Vec<LabelCondition>) {
|
|
||||||
self.host_label_groups.push(LabelGroupCondition {
|
|
||||||
operator: LabelOperator::Not,
|
|
||||||
label_group: labels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn excluding_host_labels(mut self, labels: Vec<LabelCondition>) -> Self {
|
|
||||||
self.exclude_host_labels(labels);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a service label group that must ALL match (AND).
|
|
||||||
pub fn require_service_labels(&mut self, labels: Vec<LabelCondition>) {
|
|
||||||
self.service_label_groups.push(LabelGroupCondition {
|
|
||||||
operator: LabelOperator::And,
|
|
||||||
label_group: labels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn with_service_labels(mut self, labels: Vec<LabelCondition>) -> Self {
|
|
||||||
self.require_service_labels(labels);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a service label group where ANY must match (OR).
|
|
||||||
pub fn require_any_service_label(&mut self, labels: Vec<LabelCondition>) {
|
|
||||||
self.service_label_groups.push(LabelGroupCondition {
|
|
||||||
operator: LabelOperator::Or,
|
|
||||||
label_group: labels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn with_any_service_label(mut self, labels: Vec<LabelCondition>) -> Self {
|
|
||||||
self.require_any_service_label(labels);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add a service label group that must NOT match (NOT).
|
|
||||||
pub fn exclude_service_labels(&mut self, labels: Vec<LabelCondition>) {
|
|
||||||
self.service_label_groups.push(LabelGroupCondition {
|
|
||||||
operator: LabelOperator::Not,
|
|
||||||
label_group: labels,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
pub fn excluding_service_labels(mut self, labels: Vec<LabelCondition>) -> Self {
|
|
||||||
self.exclude_service_labels(labels);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct MatchCondition {
|
|
||||||
match_on: Vec<String>,
|
|
||||||
operator: MatchOperator,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
pub enum MatchOperator {
|
|
||||||
#[default]
|
|
||||||
OneOf,
|
|
||||||
NoneOf,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct HostTagCondition {
|
|
||||||
key: String,
|
|
||||||
match_on: TagMatchOperator,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub enum TagMatchOperator {
|
|
||||||
Is(String),
|
|
||||||
IsNot(String),
|
|
||||||
OneOff(Vec<String>),
|
|
||||||
NoneOff(Vec<String>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct LabelGroupCondition {
|
|
||||||
operator: LabelOperator,
|
|
||||||
label_group: Vec<LabelCondition>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub struct LabelCondition {
|
|
||||||
operator: LabelOperator,
|
|
||||||
label: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
|
||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
|
||||||
pub enum LabelOperator {
|
|
||||||
#[default]
|
|
||||||
And,
|
|
||||||
Or,
|
|
||||||
Not,
|
|
||||||
}
|
|
||||||
|
|
||||||
domain_client!(Rule, rule_api);
|
|
||||||
domain_create!(Rule, Rule);
|
|
||||||
domain_update!(Rule, Rule);
|
|
||||||
domain_delete!(Rule);
|
|
||||||
|
|
||||||
impl ApiClient<Rule> {
|
|
||||||
pub async fn read(&self, id: Uuid) -> Result<Rule> {
|
|
||||||
let mut object = self.inner.read_domain_object::<Rule, _>(id, &()).await?;
|
|
||||||
object.extensions.id = Some(Uuid::parse_str(&object.id)?);
|
|
||||||
Ok(object.extensions)
|
|
||||||
}
|
|
||||||
pub async fn bulk_read(&self) -> Result<Vec<Rule>> {
|
|
||||||
let objects = self.inner.bulk_read_domain_objects::<Rule, _>(&()).await?;
|
|
||||||
let objects = objects
|
|
||||||
.value
|
|
||||||
.into_iter()
|
|
||||||
.map(|mut object| {
|
|
||||||
object.extensions.id = Some(Uuid::parse_str(&object.id)?);
|
|
||||||
Ok::<_, Error>(object.extensions)
|
|
||||||
})
|
|
||||||
.collect::<Result<Vec<_>>>()?;
|
|
||||||
Ok(objects)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod serde_tags {
|
|
||||||
use serde::{
|
|
||||||
Deserialize, Serialize,
|
|
||||||
de::{self, Error, Unexpected, Visitor},
|
|
||||||
ser::SerializeStruct,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::api::rules::{HostTagCondition, TagMatchOperator};
|
|
||||||
|
|
||||||
impl Serialize for HostTagCondition {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: serde::Serializer,
|
|
||||||
{
|
|
||||||
let mut map = serializer.serialize_struct("HostTagCondition", 3)?;
|
|
||||||
|
|
||||||
map.serialize_field("key", &self.key)?;
|
|
||||||
|
|
||||||
match &self.match_on {
|
|
||||||
TagMatchOperator::Is(value) => {
|
|
||||||
map.serialize_field("operator", "is")?;
|
|
||||||
map.serialize_field("value", &value)?;
|
|
||||||
}
|
|
||||||
TagMatchOperator::IsNot(value) => {
|
|
||||||
map.serialize_field("operator", "is_not")?;
|
|
||||||
map.serialize_field("value", &value)?;
|
|
||||||
}
|
|
||||||
TagMatchOperator::OneOff(items) => {
|
|
||||||
map.serialize_field("operator", "one_of")?;
|
|
||||||
map.serialize_field("value", items)?;
|
|
||||||
}
|
|
||||||
TagMatchOperator::NoneOff(items) => {
|
|
||||||
map.serialize_field("operator", "none_of")?;
|
|
||||||
map.serialize_field("value", items)?;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
map.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct HostTagConditionVisitor;
|
|
||||||
|
|
||||||
impl<'de> Visitor<'de> for HostTagConditionVisitor {
|
|
||||||
type Value = HostTagCondition;
|
|
||||||
|
|
||||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
formatter.write_str("expected a struct with fields key, operator and value")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
|
||||||
where
|
|
||||||
A: serde::de::MapAccess<'de>,
|
|
||||||
{
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
#[serde(rename_all = "lowercase")]
|
|
||||||
enum Field {
|
|
||||||
Key,
|
|
||||||
Operator,
|
|
||||||
Value,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
#[serde(rename_all = "snake_case")]
|
|
||||||
enum Operator {
|
|
||||||
Is,
|
|
||||||
IsNot,
|
|
||||||
OneOff,
|
|
||||||
NoneOff,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
enum ValueKind {
|
|
||||||
Single(String),
|
|
||||||
Multiple(Vec<String>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ValueKind {
|
|
||||||
fn into_single(self) -> Option<String> {
|
|
||||||
if let Self::Single(s) = self {
|
|
||||||
Some(s)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn into_multiple(self) -> Result<Vec<String>, String> {
|
|
||||||
match self {
|
|
||||||
Self::Multiple(ss) => Ok(ss),
|
|
||||||
Self::Single(s) => Err(s),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut tkey: Option<String> = None;
|
|
||||||
let mut toperator: Option<Operator> = None;
|
|
||||||
let mut tvalue: Option<ValueKind> = None;
|
|
||||||
|
|
||||||
while let Some(key) = map.next_key()? {
|
|
||||||
#[allow(unused_must_use)]
|
|
||||||
match key {
|
|
||||||
Field::Key => {
|
|
||||||
tkey.insert(map.next_value()?);
|
|
||||||
}
|
|
||||||
Field::Operator => {
|
|
||||||
toperator.insert(map.next_value()?);
|
|
||||||
}
|
|
||||||
Field::Value => {
|
|
||||||
tvalue.insert(map.next_value()?);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let key = tkey.ok_or(A::Error::missing_field("key"))?;
|
|
||||||
let match_on = match toperator.ok_or(de::Error::missing_field("operator"))? {
|
|
||||||
Operator::Is => TagMatchOperator::Is(
|
|
||||||
tvalue
|
|
||||||
.and_then(|v| v.into_single())
|
|
||||||
.ok_or(A::Error::invalid_value(Unexpected::Seq, &"single string"))?,
|
|
||||||
),
|
|
||||||
Operator::IsNot => TagMatchOperator::IsNot(
|
|
||||||
tvalue
|
|
||||||
.and_then(|v| v.into_single())
|
|
||||||
.ok_or(A::Error::invalid_value(Unexpected::Seq, &"single string"))?,
|
|
||||||
),
|
|
||||||
Operator::OneOff => TagMatchOperator::OneOff(
|
|
||||||
tvalue
|
|
||||||
.ok_or(A::Error::missing_field("value"))?
|
|
||||||
.into_multiple()
|
|
||||||
.map_err(|s| {
|
|
||||||
A::Error::invalid_value(
|
|
||||||
Unexpected::Str(s.as_str()),
|
|
||||||
&"sequence of stirngs",
|
|
||||||
)
|
|
||||||
})?,
|
|
||||||
),
|
|
||||||
Operator::NoneOff => TagMatchOperator::NoneOff(
|
|
||||||
tvalue
|
|
||||||
.ok_or(A::Error::missing_field("value"))?
|
|
||||||
.into_multiple()
|
|
||||||
.map_err(|s| {
|
|
||||||
A::Error::invalid_value(
|
|
||||||
Unexpected::Str(s.as_str()),
|
|
||||||
&"sequence of stirngs",
|
|
||||||
)
|
|
||||||
})?,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(HostTagCondition { key, match_on })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for HostTagCondition {
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
deserializer.deserialize_map(HostTagConditionVisitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
src/api/rules/contactgroups.rs
Normal file
14
src/api/rules/contactgroups.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg(feature = "schemars")]
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
|
pub struct HostContactGroups {
|
||||||
|
pub groups: Vec<String>,
|
||||||
|
pub r#use: bool,
|
||||||
|
pub use_for_services: bool,
|
||||||
|
pub recurse_use: bool,
|
||||||
|
pub recurse_perms: bool,
|
||||||
|
}
|
||||||
2
src/api/rules/mod.rs
Normal file
2
src/api/rules/mod.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod contactgroups;
|
||||||
|
pub mod snmp;
|
||||||
77
src/api/rules/snmp.rs
Normal file
77
src/api/rules/snmp.rs
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[cfg(feature = "schemars")]
|
||||||
|
use schemars::JsonSchema;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
|
pub enum SnmpV3AuthProtocol {
|
||||||
|
#[serde(rename = "MD5-96")]
|
||||||
|
Md5,
|
||||||
|
#[serde(rename = "SHA-1-96")]
|
||||||
|
Sha96,
|
||||||
|
#[serde(rename = "SHA-2-224")]
|
||||||
|
Sha224,
|
||||||
|
#[serde(rename = "SHA-2-256")]
|
||||||
|
Sha256,
|
||||||
|
#[serde(rename = "SHA-2-384")]
|
||||||
|
Sha384,
|
||||||
|
#[serde(rename = "SHA-2-512")]
|
||||||
|
Sha512,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
|
pub struct SnmpV3Auth {
|
||||||
|
pub auth_protocol: SnmpV3AuthProtocol,
|
||||||
|
pub security_name: String,
|
||||||
|
pub auth_password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
|
pub enum SnmpV3PrivProtocol {
|
||||||
|
#[serde(rename = "CBC-DES")]
|
||||||
|
Des,
|
||||||
|
#[serde(rename = "3DES-EDE")]
|
||||||
|
Des3,
|
||||||
|
#[serde(rename = "AES-128")]
|
||||||
|
Aes128,
|
||||||
|
#[serde(rename = "AES-192")]
|
||||||
|
Aes192,
|
||||||
|
#[serde(rename = "AES-256")]
|
||||||
|
Aes256,
|
||||||
|
#[serde(rename = "AES-192-Blumenthal")]
|
||||||
|
Aes192Blumenthal,
|
||||||
|
#[serde(rename = "AES-256-Blumenthal")]
|
||||||
|
Aes256Blumenthal,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
|
pub struct SnmpV3Priv {
|
||||||
|
pub privacy_protocol: SnmpV3PrivProtocol,
|
||||||
|
pub privacy_password: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum SnmpCommunity {
|
||||||
|
V1V2Community {
|
||||||
|
community: String,
|
||||||
|
},
|
||||||
|
NoAuthNoPriv {
|
||||||
|
security_name: String,
|
||||||
|
},
|
||||||
|
AuthNoPriv {
|
||||||
|
#[serde(flatten)]
|
||||||
|
auth: SnmpV3Auth,
|
||||||
|
},
|
||||||
|
AuthPriv {
|
||||||
|
#[serde(flatten)]
|
||||||
|
authentication: SnmpV3Auth,
|
||||||
|
#[serde(flatten)]
|
||||||
|
privacy: SnmpV3Priv,
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -1,13 +1,10 @@
|
|||||||
use crate::api::Display;
|
use crate::api::Display;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "schemars")]
|
#[cfg(feature = "schemars")]
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::api::{
|
use crate::api::{DomainExtension, DomainType, domain_bulk_read, domain_client, domain_create, domain_delete, domain_read, domain_update};
|
||||||
DomainExtension, DomainType, domain_bulk_read, domain_client, domain_create, domain_delete,
|
|
||||||
domain_read, domain_update,
|
|
||||||
};
|
|
||||||
use crate::{ApiClient, Client, Result};
|
use crate::{ApiClient, Client, Result};
|
||||||
|
|
||||||
domain_client!(TagGroup, tag_api);
|
domain_client!(TagGroup, tag_api);
|
||||||
@ -18,7 +15,7 @@ pub struct ExtendedTagGroup {
|
|||||||
pub id: String,
|
pub id: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
#[serde(flatten, default)]
|
#[serde(flatten, default)]
|
||||||
pub inner: TagGroup,
|
pub inner: TagGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||||
@ -28,7 +25,7 @@ pub struct TagGroup {
|
|||||||
pub topic: String,
|
pub topic: String,
|
||||||
#[serde(default, skip_serializing_if = "String::is_empty")]
|
#[serde(default, skip_serializing_if = "String::is_empty")]
|
||||||
pub help: String,
|
pub help: String,
|
||||||
pub tags: Vec<Tag>,
|
pub tags: Vec<Tag>
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -36,16 +33,12 @@ pub struct TagGroup {
|
|||||||
pub struct Tag {
|
pub struct Tag {
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub aux_tags: Vec<String>,
|
pub aux_tags: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExtendedTagGroup {
|
impl ExtendedTagGroup {
|
||||||
pub fn new(id: String, title: String) -> Self {
|
pub fn new(id: String, title: String) -> Self {
|
||||||
Self {
|
Self { id, title, inner: Default::default() }
|
||||||
id,
|
|
||||||
title,
|
|
||||||
inner: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_topic(&mut self, topic: String) {
|
pub fn set_topic(&mut self, topic: String) {
|
||||||
@ -76,14 +69,14 @@ impl Tag {
|
|||||||
Self {
|
Self {
|
||||||
id: Some(id),
|
id: Some(id),
|
||||||
title,
|
title,
|
||||||
aux_tags: Vec::new(),
|
aux_tags: Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn new_default(title: String) -> Self {
|
pub fn new_default(title: String) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: None,
|
id: None,
|
||||||
title,
|
title,
|
||||||
aux_tags: Vec::new(),
|
aux_tags: Vec::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,16 +95,12 @@ pub struct TagUpdateRequest {
|
|||||||
title: String,
|
title: String,
|
||||||
#[serde(flatten, default)]
|
#[serde(flatten, default)]
|
||||||
inner: TagGroup,
|
inner: TagGroup,
|
||||||
repair: bool,
|
repair: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TagUpdateRequest {
|
impl TagUpdateRequest {
|
||||||
pub fn new(title: String, repair: bool) -> Self {
|
pub fn new(title: String, repair: bool) -> Self {
|
||||||
Self {
|
Self { title, repair, inner: Default::default() }
|
||||||
title,
|
|
||||||
repair,
|
|
||||||
inner: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_topic(&mut self, topic: String) {
|
pub fn set_topic(&mut self, topic: String) {
|
||||||
@ -141,7 +130,7 @@ impl TagUpdateRequest {
|
|||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
pub struct TagDeleteQuery {
|
pub struct TagDeleteQuery {
|
||||||
repair: bool,
|
repair: bool,
|
||||||
mode: Option<TagDeleteMode>,
|
mode: Option<TagDeleteMode>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TagDeleteQuery {
|
impl TagDeleteQuery {
|
||||||
@ -154,8 +143,7 @@ impl TagDeleteQuery {
|
|||||||
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
#[cfg_attr(feature = "schemars", derive(JsonSchema))]
|
||||||
pub enum TagDeleteMode {
|
pub enum TagDeleteMode {
|
||||||
Abort,
|
Abort,
|
||||||
#[default]
|
#[default] Delete,
|
||||||
Delete,
|
|
||||||
Remove,
|
Remove,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,9 @@ use serde::Serialize;
|
|||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use tokio::sync::Semaphore;
|
use tokio::sync::Semaphore;
|
||||||
|
|
||||||
use crate::api::{DomainCollection, DomainType};
|
use crate::api::{
|
||||||
|
DomainCollection, DomainType,
|
||||||
|
};
|
||||||
use crate::{Error, Result};
|
use crate::{Error, Result};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -222,9 +224,15 @@ impl InnerClient {
|
|||||||
pub(crate) async fn handle_request(&self, request: Request) -> Result<String> {
|
pub(crate) async fn handle_request(&self, request: Request) -> Result<String> {
|
||||||
let permit = self.semaphore.acquire().await.unwrap();
|
let permit = self.semaphore.acquire().await.unwrap();
|
||||||
debug!("sending {}-request to {}", request.method(), request.url());
|
debug!("sending {}-request to {}", request.method(), request.url());
|
||||||
if let Some(body) = request.body().as_ref().and_then(|b| b.as_bytes()) {
|
trace!(
|
||||||
trace!("with body: {}", String::from_utf8_lossy(body))
|
"with body: {}",
|
||||||
}
|
request
|
||||||
|
.body()
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|b| b.as_bytes())
|
||||||
|
.map(String::from_utf8_lossy)
|
||||||
|
.unwrap_or_default()
|
||||||
|
);
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.http
|
.http
|
||||||
@ -280,11 +288,11 @@ impl InnerClient {
|
|||||||
&self,
|
&self,
|
||||||
domain_type: DomainType,
|
domain_type: DomainType,
|
||||||
object: &O,
|
object: &O,
|
||||||
query: &Q,
|
query: &Q
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
O: Serialize,
|
O: Serialize,
|
||||||
Q: Serialize,
|
Q: Serialize
|
||||||
{
|
{
|
||||||
let url = self.collection_url(domain_type);
|
let url = self.collection_url(domain_type);
|
||||||
let request = self
|
let request = self
|
||||||
@ -306,10 +314,15 @@ impl InnerClient {
|
|||||||
) -> Result<O>
|
) -> Result<O>
|
||||||
where
|
where
|
||||||
O: DeserializeOwned,
|
O: DeserializeOwned,
|
||||||
Q: Serialize,
|
Q: Serialize
|
||||||
{
|
{
|
||||||
let url = self.object_url(domain_type, id);
|
let url = self.object_url(domain_type, id);
|
||||||
let request = self.http.get(url).query(query).build().unwrap();
|
let request = self
|
||||||
|
.http
|
||||||
|
.get(url)
|
||||||
|
.query(query)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.query_api(request).await
|
self.query_api(request).await
|
||||||
}
|
}
|
||||||
@ -345,7 +358,12 @@ impl InnerClient {
|
|||||||
Q: Serialize,
|
Q: Serialize,
|
||||||
{
|
{
|
||||||
let url = self.object_url(domain_type, id);
|
let url = self.object_url(domain_type, id);
|
||||||
let request = self.http.delete(url).query(&query).build().unwrap();
|
let request = self
|
||||||
|
.http
|
||||||
|
.delete(url)
|
||||||
|
.query(&query)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.invoke_api(request).await
|
self.invoke_api(request).await
|
||||||
}
|
}
|
||||||
@ -381,18 +399,27 @@ impl InnerClient {
|
|||||||
pub(crate) async fn bulk_read<O, Q>(
|
pub(crate) async fn bulk_read<O, Q>(
|
||||||
&self,
|
&self,
|
||||||
domain_type: DomainType,
|
domain_type: DomainType,
|
||||||
query: &Q,
|
query: &Q
|
||||||
) -> Result<DomainCollection<O>>
|
) -> Result<DomainCollection<O>>
|
||||||
where
|
where
|
||||||
O: DeserializeOwned,
|
O: DeserializeOwned,
|
||||||
Q: Serialize,
|
Q: Serialize
|
||||||
{
|
{
|
||||||
let url = self.collection_url(domain_type);
|
let url = self.collection_url(domain_type);
|
||||||
let request = self.http.get(url).query(query).build().unwrap();
|
let request = self.http
|
||||||
|
.get(url)
|
||||||
|
.query(query)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.query_api(request).await
|
self.query_api(request).await
|
||||||
|
|
||||||
}
|
}
|
||||||
pub(crate) async fn bulk_update<O>(&self, domain_type: DomainType, entries: &[O]) -> Result<()>
|
pub(crate) async fn bulk_update<O>(
|
||||||
|
&self,
|
||||||
|
domain_type: DomainType,
|
||||||
|
entries: &[O],
|
||||||
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
O: Serialize,
|
O: Serialize,
|
||||||
{
|
{
|
||||||
@ -404,14 +431,19 @@ impl InnerClient {
|
|||||||
let url = self.bulk_action_url(domain_type, BulkAction::Update);
|
let url = self.bulk_action_url(domain_type, BulkAction::Update);
|
||||||
let body = Request::<O> { entries };
|
let body = Request::<O> { entries };
|
||||||
|
|
||||||
let request = self.http.put(url).json(&body).build().unwrap();
|
let request = self
|
||||||
|
.http
|
||||||
|
.put(url)
|
||||||
|
.json(&body)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.invoke_api(request).await
|
self.invoke_api(request).await
|
||||||
}
|
}
|
||||||
pub(crate) async fn bulk_delete(
|
pub(crate) async fn bulk_delete(
|
||||||
&self,
|
&self,
|
||||||
domain_type: DomainType,
|
domain_type: DomainType,
|
||||||
entries: &[String],
|
entries: &[String]
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Request<'a> {
|
struct Request<'a> {
|
||||||
@ -421,7 +453,12 @@ impl InnerClient {
|
|||||||
let url = self.bulk_action_url(domain_type, BulkAction::Delete);
|
let url = self.bulk_action_url(domain_type, BulkAction::Delete);
|
||||||
let body = Request { entries };
|
let body = Request { entries };
|
||||||
|
|
||||||
let request = self.http.post(url).json(&body).build().unwrap();
|
let request = self
|
||||||
|
.http
|
||||||
|
.post(url)
|
||||||
|
.json(&body)
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.invoke_api(request).await
|
self.invoke_api(request).await
|
||||||
}
|
}
|
||||||
@ -450,7 +487,7 @@ pub struct ApiClient<D> {
|
|||||||
_marker: PhantomData<D>,
|
_marker: PhantomData<D>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<D> ApiClient<D> {
|
impl <D> ApiClient<D> {
|
||||||
pub(crate) fn new(inner: &Client) -> Self {
|
pub(crate) fn new(inner: &Client) -> Self {
|
||||||
Self {
|
Self {
|
||||||
inner: inner.0.clone(),
|
inner: inner.0.clone(),
|
||||||
|
|||||||
@ -32,8 +32,6 @@ pub enum Error {
|
|||||||
MissingHeader(&'static str),
|
MissingHeader(&'static str),
|
||||||
#[error("Failed to parse ETag header: {0}")]
|
#[error("Failed to parse ETag header: {0}")]
|
||||||
ParseEtag(#[source] std::string::FromUtf8Error),
|
ParseEtag(#[source] std::string::FromUtf8Error),
|
||||||
#[error("failed to parse domain object id: {0}")]
|
|
||||||
ParseId(#[from] uuid::Error),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|||||||
130
src/main.rs
130
src/main.rs
@ -8,11 +8,13 @@ const PASSWORD: &str = "C5t71DUPAu2D";
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
let log_config = simplelog::ConfigBuilder::new()
|
||||||
|
.set_location_level(simplelog::LevelFilter::Error)
|
||||||
|
.build();
|
||||||
|
|
||||||
simplelog::TermLogger::init(
|
simplelog::TermLogger::init(
|
||||||
simplelog::LevelFilter::Trace,
|
simplelog::LevelFilter::Trace,
|
||||||
simplelog::ConfigBuilder::new()
|
log_config,
|
||||||
.set_location_level(simplelog::LevelFilter::Error)
|
|
||||||
.build(),
|
|
||||||
simplelog::TerminalMode::Stderr,
|
simplelog::TerminalMode::Stderr,
|
||||||
simplelog::ColorChoice::Auto,
|
simplelog::ColorChoice::Auto,
|
||||||
)
|
)
|
||||||
@ -31,7 +33,6 @@ async fn main() -> Result<()> {
|
|||||||
test_host_groups(client.clone()).await?;
|
test_host_groups(client.clone()).await?;
|
||||||
test_service_groups(client.clone()).await?;
|
test_service_groups(client.clone()).await?;
|
||||||
test_contact_groups(client.clone()).await?;
|
test_contact_groups(client.clone()).await?;
|
||||||
test_rulesets(client.clone()).await?;
|
|
||||||
test_activations(client.clone()).await?;
|
test_activations(client.clone()).await?;
|
||||||
|
|
||||||
info!("tests done; all pass");
|
info!("tests done; all pass");
|
||||||
@ -92,8 +93,8 @@ async fn test_folders(client: Client) -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn test_hosts(client: Client) -> Result<()> {
|
async fn test_hosts(client: Client) -> Result<()> {
|
||||||
use checkmk_api::api::folders::FolderAttributes;
|
|
||||||
use checkmk_api::api::hosts::*;
|
use checkmk_api::api::hosts::*;
|
||||||
|
use checkmk_api::api::folders::FolderAttributes;
|
||||||
const TESTHOST: &str = "test-host";
|
const TESTHOST: &str = "test-host";
|
||||||
info!("testing hosts");
|
info!("testing hosts");
|
||||||
|
|
||||||
@ -101,17 +102,17 @@ async fn test_hosts(client: Client) -> Result<()> {
|
|||||||
let creq = HostCreationRequest::new(
|
let creq = HostCreationRequest::new(
|
||||||
TESTHOST.to_string(),
|
TESTHOST.to_string(),
|
||||||
"~".to_string(),
|
"~".to_string(),
|
||||||
FolderAttributes::default().with_site("dev".to_string()),
|
FolderAttributes::default().with_site("dev".to_string())
|
||||||
);
|
);
|
||||||
let cquery = HostCreationQuery::new(false);
|
let cquery = HostCreationQuery::new(false);
|
||||||
let rquery = HostReadQuery::new(true);
|
let rquery = HostReadQuery::new(true);
|
||||||
let ureq1 = HostUpdateRequest::replace(
|
let ureq1 = HostUpdateRequest::replace(
|
||||||
FolderAttributes::default()
|
FolderAttributes::default()
|
||||||
.with_site("dev".to_string())
|
.with_site("dev".to_string())
|
||||||
.with_label("environment".to_string(), "test".to_string()),
|
.with_label("environment".to_string(), "test".to_string())
|
||||||
);
|
);
|
||||||
let ureq2 = HostUpdateRequest::update(
|
let ureq2 = HostUpdateRequest::update(
|
||||||
FolderAttributes::default().with_label("purpose".to_string(), "testing".to_string()),
|
FolderAttributes::default().with_label("purpose".to_string(), "testing".to_string())
|
||||||
);
|
);
|
||||||
|
|
||||||
info!("creating test host");
|
info!("creating test host");
|
||||||
@ -210,10 +211,7 @@ async fn test_host_groups(client: Client) -> Result<()> {
|
|||||||
let api = client.host_group_api();
|
let api = client.host_group_api();
|
||||||
|
|
||||||
info!("creating test host group");
|
info!("creating test host group");
|
||||||
api.create(&HostGroup::new(
|
api.create(&HostGroup::new(TESTGROUP.to_string(), "Test Host Group".to_string()))
|
||||||
TESTGROUP.to_string(),
|
|
||||||
"Test Host Group".to_string(),
|
|
||||||
))
|
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to create host group: {e}"))?;
|
.inspect_err(|e| error!("failed to create host group: {e}"))?;
|
||||||
|
|
||||||
@ -230,14 +228,8 @@ async fn test_host_groups(client: Client) -> Result<()> {
|
|||||||
|
|
||||||
info!("bulk creating additional host groups");
|
info!("bulk creating additional host groups");
|
||||||
api.bulk_create(&[
|
api.bulk_create(&[
|
||||||
HostGroup::new(
|
HostGroup::new("test-host-group-2".to_string(), "Test Host Group 2".to_string()),
|
||||||
"test-host-group-2".to_string(),
|
HostGroup::new("test-host-group-3".to_string(), "Test Host Group 3".to_string()),
|
||||||
"Test Host Group 2".to_string(),
|
|
||||||
),
|
|
||||||
HostGroup::new(
|
|
||||||
"test-host-group-3".to_string(),
|
|
||||||
"Test Host Group 3".to_string(),
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to bulk create host groups: {e}"))?;
|
.inspect_err(|e| error!("failed to bulk create host groups: {e}"))?;
|
||||||
@ -250,14 +242,8 @@ async fn test_host_groups(client: Client) -> Result<()> {
|
|||||||
|
|
||||||
info!("bulk updating host groups");
|
info!("bulk updating host groups");
|
||||||
api.bulk_update(&[
|
api.bulk_update(&[
|
||||||
Group::new(
|
Group::new("test-host-group-2".to_string(), "Updated Host Group 2".to_string()),
|
||||||
"test-host-group-2".to_string(),
|
Group::new("test-host-group-3".to_string(), "Updated Host Group 3".to_string()),
|
||||||
"Updated Host Group 2".to_string(),
|
|
||||||
),
|
|
||||||
Group::new(
|
|
||||||
"test-host-group-3".to_string(),
|
|
||||||
"Updated Host Group 3".to_string(),
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to bulk update host groups: {e}"))?;
|
.inspect_err(|e| error!("failed to bulk update host groups: {e}"))?;
|
||||||
@ -286,10 +272,7 @@ async fn test_service_groups(client: Client) -> Result<()> {
|
|||||||
let api = client.service_group_api();
|
let api = client.service_group_api();
|
||||||
|
|
||||||
info!("creating test service group");
|
info!("creating test service group");
|
||||||
api.create(&ServiceGroup::new(
|
api.create(&ServiceGroup::new(TESTGROUP.to_string(), "Test Service Group".to_string()))
|
||||||
TESTGROUP.to_string(),
|
|
||||||
"Test Service Group".to_string(),
|
|
||||||
))
|
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to create service group: {e}"))?;
|
.inspect_err(|e| error!("failed to create service group: {e}"))?;
|
||||||
|
|
||||||
@ -306,14 +289,8 @@ async fn test_service_groups(client: Client) -> Result<()> {
|
|||||||
|
|
||||||
info!("bulk creating additional service groups");
|
info!("bulk creating additional service groups");
|
||||||
api.bulk_create(&[
|
api.bulk_create(&[
|
||||||
ServiceGroup::new(
|
ServiceGroup::new("test-service-group-2".to_string(), "Test Service Group 2".to_string()),
|
||||||
"test-service-group-2".to_string(),
|
ServiceGroup::new("test-service-group-3".to_string(), "Test Service Group 3".to_string()),
|
||||||
"Test Service Group 2".to_string(),
|
|
||||||
),
|
|
||||||
ServiceGroup::new(
|
|
||||||
"test-service-group-3".to_string(),
|
|
||||||
"Test Service Group 3".to_string(),
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to bulk create service groups: {e}"))?;
|
.inspect_err(|e| error!("failed to bulk create service groups: {e}"))?;
|
||||||
@ -326,14 +303,8 @@ async fn test_service_groups(client: Client) -> Result<()> {
|
|||||||
|
|
||||||
info!("bulk updating service groups");
|
info!("bulk updating service groups");
|
||||||
api.bulk_update(&[
|
api.bulk_update(&[
|
||||||
Group::new(
|
Group::new("test-service-group-2".to_string(), "Updated Service Group 2".to_string()),
|
||||||
"test-service-group-2".to_string(),
|
Group::new("test-service-group-3".to_string(), "Updated Service Group 3".to_string()),
|
||||||
"Updated Service Group 2".to_string(),
|
|
||||||
),
|
|
||||||
Group::new(
|
|
||||||
"test-service-group-3".to_string(),
|
|
||||||
"Updated Service Group 3".to_string(),
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to bulk update service groups: {e}"))?;
|
.inspect_err(|e| error!("failed to bulk update service groups: {e}"))?;
|
||||||
@ -393,44 +364,6 @@ async fn test_activations(client: Client) -> Result<()> {
|
|||||||
Ok(())
|
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<()> {
|
async fn test_contact_groups(client: Client) -> Result<()> {
|
||||||
use checkmk_api::api::groups::*;
|
use checkmk_api::api::groups::*;
|
||||||
const TESTGROUP: &str = "test-contact-group";
|
const TESTGROUP: &str = "test-contact-group";
|
||||||
@ -439,10 +372,7 @@ async fn test_contact_groups(client: Client) -> Result<()> {
|
|||||||
let api = client.contact_group_api();
|
let api = client.contact_group_api();
|
||||||
|
|
||||||
info!("creating test contact group");
|
info!("creating test contact group");
|
||||||
api.create(&ContactGroup::new(
|
api.create(&ContactGroup::new(TESTGROUP.to_string(), "Test Contact Group".to_string()))
|
||||||
TESTGROUP.to_string(),
|
|
||||||
"Test Contact Group".to_string(),
|
|
||||||
))
|
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to create contact group: {e}"))?;
|
.inspect_err(|e| error!("failed to create contact group: {e}"))?;
|
||||||
|
|
||||||
@ -459,14 +389,8 @@ async fn test_contact_groups(client: Client) -> Result<()> {
|
|||||||
|
|
||||||
info!("bulk creating additional contact groups");
|
info!("bulk creating additional contact groups");
|
||||||
api.bulk_create(&[
|
api.bulk_create(&[
|
||||||
ContactGroup::new(
|
ContactGroup::new("test-contact-group-2".to_string(), "Test Contact Group 2".to_string()),
|
||||||
"test-contact-group-2".to_string(),
|
ContactGroup::new("test-contact-group-3".to_string(), "Test Contact Group 3".to_string()),
|
||||||
"Test Contact Group 2".to_string(),
|
|
||||||
),
|
|
||||||
ContactGroup::new(
|
|
||||||
"test-contact-group-3".to_string(),
|
|
||||||
"Test Contact Group 3".to_string(),
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to bulk create contact groups: {e}"))?;
|
.inspect_err(|e| error!("failed to bulk create contact groups: {e}"))?;
|
||||||
@ -479,14 +403,8 @@ async fn test_contact_groups(client: Client) -> Result<()> {
|
|||||||
|
|
||||||
info!("bulk updating contact groups");
|
info!("bulk updating contact groups");
|
||||||
api.bulk_update(&[
|
api.bulk_update(&[
|
||||||
Group::new(
|
Group::new("test-contact-group-2".to_string(), "Updated Contact Group 2".to_string()),
|
||||||
"test-contact-group-2".to_string(),
|
Group::new("test-contact-group-3".to_string(), "Updated Contact Group 3".to_string()),
|
||||||
"Updated Contact Group 2".to_string(),
|
|
||||||
),
|
|
||||||
Group::new(
|
|
||||||
"test-contact-group-3".to_string(),
|
|
||||||
"Updated Contact Group 3".to_string(),
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
.await
|
.await
|
||||||
.inspect_err(|e| error!("failed to bulk update contact groups: {e}"))?;
|
.inspect_err(|e| error!("failed to bulk update contact groups: {e}"))?;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user