diff --git a/MONITOR_TYPES.md b/MONITOR_TYPES.md index ab28e06..de5a69c 100644 --- a/MONITOR_TYPES.md +++ b/MONITOR_TYPES.md @@ -1,221 +1,421 @@ -## `ping` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `hostname` | localhost | -| `packet_size` | 56 | -| `accepted_statuscodes` | 200-299 | +# Monitor Types +- [`dns`](#dns) +- [`docker`](#docker) +- [`gamedig`](#gamedig) +- [`group`](#group) +- [`grpc-keyword`](#grpc-keyword) +- [`http`](#http) +- [`json-query`](#json-query) +- [`kafka-producer`](#kafka-producer) +- [`keyword`](#keyword) +- [`mongodb`](#mongodb) +- [`mqtt`](#mqtt) +- [`mysql`](#mysql) +- [`ping`](#ping) +- [`port`](#port) +- [`postgres`](#postgres) +- [`push`](#push) +- [`radius`](#radius) +- [`real-browser`](#real-browser) +- [`redis`](#redis) +- [`steam`](#steam) +- [`sqlserver`](#sqlserver) +- [`tailscale-ping`](#tailscale-ping) -## `mqtt` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `hostname` | localhost | -| `port` | 0 | -| `mqtt_username` | null | -| `mqtt_password` | null | -| `mqtt_topic` | "" | -| `mqtt_check_type` | null | -| `mqtt_success_message` | null | -## `redis` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `database_connection_string` | null | -| `accepted_statuscodes` | 200-299 | +## `dns` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `dns_resolve_server` | 1.1.1.1 | +| `dns_resolve_type` | A | +| `hostname` | localhost | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `port` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `push` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `push_url` | null | -| `accepted_statuscodes` | 200-299 | +## `docker` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `docker_container` | | +| `docker_host` | | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `mysql` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `database_connection_string` | null | -| `radius_password` | "" | -| `accepted_statuscodes` | 200-299 | +## `gamedig` +| Property | Example Value | +|---------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `game` | | +| `gamedig_given_port_only` | | +| `hostname` | localhost | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `port` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `docker` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `docker_container` | "" | -| `docker_host` | "" | -| `accepted_statuscodes` | 200-299 | +## `group` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `tailscale-ping` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `accepted_statuscodes` | 200-299 | +## `grpc-keyword` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `grpc_body` | | +| `grpc_enable_tls` | | +| `grpc_metadata` | | +| `grpc_method` | | +| `grpc_protobuf` | | +| `grpc_service_name` | | +| `grpc_url` | | +| `interval` | 60 | +| `invert_keyword` | | +| `keyword` | | +| `max_retries` | 0 | +| `max_redirects` | 10 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `radius` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `hostname` | localhost | -| `port` | 0 | -| `radius_username` | "" | -| `radius_password` | "" | -| `radius_secret` | "" | -| `radius_called_station_id` | "" | -| `radius_calling_station_id` | "" | -| `accepted_statuscodes` | 200-299 | +## `http` +| Property | Example Value | +|------------------------|---------------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `auth_domain` | | +| `auth_method` | | +| `auth_workstation` | | +| `basic_auth_user` | | +| `body` | | +| `expiry_notification` | true | +| `http_body_encoding` | | +| `ignore_tls` | false | +| `interval` | 60 | +| `max_redirects` | 10 | +| `max_retries` | 0 | +| `method` | GET | +| `name` | Example | +| `oauth_auth_method` | | +| `oauth_client_id` | | +| `oauth_client_secret` | | +| `oauth_scopes` | | +| `oauth_token_url` | | +| `parent` | 0 | +| `proxy_id` | | +| `resend_interval` | 60 | +| `retry_interval` | 60 | +| `timeout` | 48 | +| `tls_ca` | | +| `tls_cert` | | +| `tls_key` | | +| `upside_down` | bool | +| `url` | https://example.com | + +## `json-query` +| Property | Example Value | +|------------------------|---------------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `auth_domain` | | +| `auth_method` | | +| `auth_workstation` | | +| `basic_auth_user` | | +| `body` | | +| `expected_value` | | +| `expiry_notification` | true | +| `http_body_encoding` | | +| `ignore_tls` | false | +| `interval` | 60 | +| `json_path` | | +| `max_redirects` | 10 | +| `max_retries` | 0 | +| `method` | GET | +| `name` | Example | +| `oauth_auth_method` | | +| `oauth_client_id` | | +| `oauth_client_secret` | | +| `oauth_scopes` | | +| `oauth_token_url` | | +| `parent` | 0 | +| `proxy_id` | | +| `resend_interval` | 60 | +| `retry_interval` | 60 | +| `timeout` | 48 | +| `tls_ca` | | +| `tls_cert` | | +| `tls_key` | | +| `upside_down` | bool | +| `url` | https://example.com | ## `kafka-producer` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `kafka_producer_brokers` | null | -| `kafka_producer_topic` | null | -| `kafka_producer_message` | null | -| `kafka_producer_ssl` | null | -| `kafka_producer_allow_auto_topic_creation` | null | -| `accepted_statuscodes` | 200-299 | +| Property | Example Value | +|------------------------------------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `interval` | 60 | +| `kafka_producer_allow_auto_topic_creation` | | +| `kafka_producer_brokers` | | +| `kafka_producer_message` | | +| `kafka_producer_ssl` | | +| `kafka_producer_topic` | | +| `kafka_producer_sasl_options.mechanism` | plain | +| `kafka_producer_sasl_options.username` | | +| `kafka_producer_sasl_options.password` | | +| `kafka_producer_sasl_options.authorization_identity` | | +| `kafka_producer_sasl_options.access_key_id` | | +| `kafka_producer_sasl_options.secret_access_key` | | +| `kafka_producer_sasl_options.session_token` | | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `gamedig` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `game` | "" | -| `hostname` | localhost | -| `port` | 0 | -| `gamedig_given_port_only` | null | -| `accepted_statuscodes` | 200-299 | +## `keyword` +| Property | Example Value | +|------------------------|---------------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `auth_domain` | | +| `auth_method` | | +| `auth_workstation` | | +| `basic_auth_user` | | +| `body` | | +| `expiry_notification` | true | +| `http_body_encoding` | | +| `ignore_tls` | false | +| `interval` | 60 | +| `invert_keyword` | | +| `keyword` | | +| `max_redirects` | 10 | +| `max_retries` | 0 | +| `method` | GET | +| `method` | GET | +| `name` | Example | +| `oauth_auth_method` | | +| `oauth_client_id` | | +| `oauth_client_secret` | | +| `oauth_scopes` | | +| `oauth_token_url` | | +| `parent` | 0 | +| `proxy_id` | | +| `resend_interval` | 60 | +| `retry_interval` | 60 | +| `timeout` | 48 | +| `tls_ca` | | +| `tls_cert` | | +| `tls_key` | | +| `upside_down` | bool | +| `url` | https://example.com | -## `real-browser` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `url` | https://example.com | -| `remote_browsers_toggle` | null | -| `remote_browser` | null | -| `accepted_statuscodes` | 200-299 | +## `mongodb` +| Property | Example Value | +|------------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `database_connection_string` | | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `sqlserver` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `database_connection_string` | null | -| `accepted_statuscodes` | 200-299 | +## `mqtt` +| Property | Example Value | +|------------------------|---------------| +| `active` | true | +| `hostname` | localhost | +| `interval` | 60 | +| `max_retries` | 0 | +| `mqtt_check_type` | | +| `mqtt_password` | | +| `mqtt_success_message` | | +| `mqtt_topic` | | +| `mqtt_username` | | +| `name` | Example | +| `parent` | 0 | +| `port` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `group` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `accepted_statuscodes` | 200-299 | +## `mysql` +| Property | Example Value | +|------------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `database_connection_string` | | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `radius_password` | | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `http` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `url` | https://example.com | -| `timeout` | 48 | -| `method` | GET | -| `accepted_statuscodes` | 200-299 | +## `ping` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `hostname` | localhost | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `packet_size` | 56 | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `grpc-keyword` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `keyword` | "" | -| `invert_keyword` | null | -| `grpc_url` | "" | -| `maxredirects` | 10 | -| `grpc_enable_tls` | null | -| `grpc_service_name` | "" | -| `grpc_method` | "" | -| `grpc_protobuf` | null | -| `grpc_body` | null | -| `grpc_metadata` | null | -| `accepted_statuscodes` | 200-299 | +## `port` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `hostname` | localhost | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `port` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `mongodb` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `database_connection_string` | null | -| `accepted_statuscodes` | 200-299 | +## `postgres` +| Property | Example Value | +|------------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `database_connection_string` | | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `keyword` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `url` | https://example.com | -| `timeout` | 48 | -| `method` | GET | -| `keyword` | "" | -| `invert_keyword` | null | -| `accepted_statuscodes` | 200-299 | +## `push` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `push_url` | | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `json-query` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `url` | https://example.com | -| `timeout` | 48 | -| `json_path` | null | -| `expected_Example value` | null - - | -| `accepted_statuscodes` | 200-299 | +## `radius` +| Property | Example Value | +|-----------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `hostname` | localhost | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `port` | 0 | +| `radius_called_station_id` | | +| `radius_calling_station_id` | | +| `radius_password` | | +| `radius_secret` | | +| `radius_username` | | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `steam` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `hostname` | localhost | -| `port` | 0 | -| `accepted_statuscodes` | 200-299 | +## `real-browser` +| Property | Example Value | +|--------------------------|---------------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `remote_browser` | | +| `remote_browsers_toggle` | | +| `retry_interval` | 60 | +| `upside_down` | bool | +| `url` | https://example.com | -## `dns` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `hostname` | localhost | -| `dns_resolve_server` | 1.1.1.1 | -| `port` | 0 | -| `dns_resolve_type` | A | -| `accepted_statuscodes` | 200-299 | +## `redis` +| Property | Example Value | +|------------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `database_connection_string` | | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `port` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `hostname` | localhost | -| `port` | 0 | -| `accepted_statuscodes` | 200-299 | +## `steam` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `hostname` | localhost | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `port` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | -## `postgres` -| Property | Example Value | -|----------|---------------| -| `name` | Example | -| `interval` | 60 | -| `database_connection_string` | null | -| `accepted_statuscodes` | 200-299 | \ No newline at end of file +## `sqlserver` +| Property | Example Value | +|------------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `database_connection_string` | | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | + +## `tailscale-ping` +| Property | Example Value | +|------------------------|---------------| +| `accepted_statuscodes` | 200-299 | +| `active` | true | +| `hostname` | localhost | +| `interval` | 60 | +| `max_retries` | 0 | +| `name` | Example | +| `parent` | 0 | +| `retry_interval` | 60 | +| `upside_down` | bool | \ No newline at end of file diff --git a/README.md b/README.md index ae211f5..f4a2f4d 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ AutoKuma is a utility that automates the creation of Uptime Kuma monitors based ## 🔧 How to Install -The AutoKuma Docker container is available on [GitHub Container Registry (GHCR)](https://ghcr.io/username/autokuma). To install, simply pull the container using: +The AutoKuma Docker container is available on [GitHub Container Registry (GHCR)](https://github.com/BigBoot/AutoKuma/pkgs/container/autokuma). To install, simply pull the container using: ```bash docker pull ghcr.io/bigboot/autokuma:master @@ -25,19 +25,19 @@ version: '3' services: autokuma: image: ghcr.io/bigboot/autokuma:master + restart: unless-stopped environment: - AUTOKUMA__KUMA__URL=http://localhost:3001 - - AUTOKUMA__KUMA__USERNAME= - - AUTOKUMA__KUMA__PASSWORD= - - AUTOKUMA__KUMA__MFA_TOKEN= - - AUTOKUMA__KUMA__HEADERS="=, =, ..." - - AUTOKUMA__KUMA__TAG_NAME=AutoKuma - - AUTOKUMA__KUMA__TAG_COLOR=#42C0FB - - AUTOKUMA__DOCKER__SOCKET=/var/run/docker.sock - - AUTOKUMA__DOCKER__LABEL_PREFIX=kuma - labels: - - "kuma.example.http.name=Example" - - "kuma.example.http.url=https://example.com" + # - AUTOKUMA__KUMA__USERNAME= + # - AUTOKUMA__KUMA__PASSWORD= + # - AUTOKUMA__KUMA__MFA_TOKEN= + # - AUTOKUMA__KUMA__HEADERS="=,=,..." + # - AUTOKUMA__KUMA__TAG_NAME=AutoKuma + # - AUTOKUMA__KUMA__TAG_COLOR=#42C0FB + # - AUTOKUMA__DOCKER__SOCKET=/var/run/docker.sock + # - AUTOKUMA__DOCKER__LABEL_PREFIX=kuma + volumes: + - /var/run/docker.sock:/var/run/docker.sock ``` ## Configuration @@ -74,8 +74,6 @@ AutoKuma interprets Docker container labels with the following format: Labels are grouped by `` into a single monitor. For example, to create a simple HTTP monitor, use the following labels: -### Example Labels - ```plaintext kuma.example.http.name: "Example" kuma.example.http.url: "https://example.com" diff --git a/src/kuma/client.rs b/src/kuma/client.rs index aa71638..57cf3b7 100644 --- a/src/kuma/client.rs +++ b/src/kuma/client.rs @@ -223,7 +223,7 @@ impl Worker { .find(|x| { x.1.monitor_type() == MonitorType::Group && x.1.common().tags.iter().any(|tag| { - tag.name == "AutoKuma" + tag.name.as_ref().is_some_and(|tag| tag == "AutoKuma") && tag .value .as_ref() diff --git a/src/kuma/models.rs b/src/kuma/models.rs index 49c6dc4..6896db1 100644 --- a/src/kuma/models.rs +++ b/src/kuma/models.rs @@ -6,477 +6,609 @@ use serde_with::{serde_as, skip_serializing_none}; use std::collections::HashMap; use strum::EnumString; -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub enum DnsResolverType { - A, - AAAA, - CAA, - CNAME, - MX, - NS, - PTR, - SOA, - SRV, - TXT, -} - #[derive(Debug, EnumString)] #[strum(serialize_all = "camelCase")] pub enum Event { + ApiKeyList, + AutoLogin, + AvgPing, + CertInfo, Connect, Disconnect, - MonitorList, - NotificationList, - ProxyList, - StatusPageList, + DockerHostList, + Heartbeat, HeartbeatList, ImportantHeartbeatList, - AvgPing, - Uptime, - Heartbeat, Info, - CertInfo, - DockerHostList, - AutoLogin, InitServerTimezone, MaintenanceList, - ApiKeyList, + MonitorList, + NotificationList, + ProxyList, + StatusPageList, + Uptime, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub enum MonitorType { - #[serde(rename = "group")] - Group, - #[serde(rename = "http")] - Http, - #[serde(rename = "port")] - Port, - #[serde(rename = "ping")] - Ping, - #[serde(rename = "keyword")] - Keyword, - #[serde(rename = "json-query")] - JsonQuery, - #[serde(rename = "grpc-keyword")] - GrpcKeyword, #[serde(rename = "dns")] Dns, + #[serde(rename = "docker")] Docker, - #[serde(rename = "real-browser")] - RealBrowser, - #[serde(rename = "push")] - Push, - #[serde(rename = "steam")] - Steam, + #[serde(rename = "gamedig")] GameDig, - #[serde(rename = "mqtt")] - Mqtt, + + #[serde(rename = "group")] + Group, + + #[serde(rename = "grpc-keyword")] + GrpcKeyword, + + #[serde(rename = "http")] + Http, + + #[serde(rename = "json-query")] + JsonQuery, + #[serde(rename = "kafka-producer")] KafkaProducer, - #[serde(rename = "sqlserver")] - SqlServer, - #[serde(rename = "postgres")] - Postgres, - #[serde(rename = "mysql")] - Mysql, + + #[serde(rename = "keyword")] + Keyword, + #[serde(rename = "mongodb")] Mongodb, + + #[serde(rename = "mqtt")] + Mqtt, + + #[serde(rename = "mysql")] + Mysql, + + #[serde(rename = "ping")] + Ping, + + #[serde(rename = "port")] + Port, + + #[serde(rename = "postgres")] + Postgres, + + #[serde(rename = "push")] + Push, + #[serde(rename = "radius")] Radius, + + #[serde(rename = "real-browser")] + RealBrowser, + #[serde(rename = "redis")] Redis, + + #[serde(rename = "steam")] + Steam, + + #[serde(rename = "sqlserver")] + SqlServer, + #[serde(rename = "tailscale-ping")] TailscalePing, } -#[derive(Debug, Serialize, Deserialize, PartialEq)] -pub enum KafkaProducerSaslOption { +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum DnsResolverType { + A, + AAAA, + CAA, + CNAME, + MX, + NS, + PTR, + SOA, + SRV, + TXT, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub enum HttpMethod { + DELETE, + GET, + HEAD, + OPTIONS, + PATCH, + POST, + PUT, +} + +#[skip_serializing_none] +#[serde_alias(SnakeCase)] +#[serde_as] +#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize)] +pub struct Tag { + #[serde(rename = "id")] + #[serde_as(as = "Option")] + pub id: Option, + + #[serde(rename = "name")] + pub name: Option, + + #[serde(rename = "color")] + pub color: Option, + + #[serde(rename = "tag_id")] + #[serde_as(as = "Option")] + pub tag_id: Option, + + #[serde(rename = "value")] + pub value: Option, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +#[serde(tag = "mechanism")] +pub enum KafkaProducerSaslOptions { #[serde(rename = "None")] None, + #[serde(rename = "plain")] Plain { #[serde(rename = "username")] username: Option, + #[serde(rename = "password")] password: Option, }, + #[serde(rename = "scram-sha-256")] ScramSha256 { #[serde(rename = "username")] username: Option, + #[serde(rename = "password")] password: Option, }, + #[serde(rename = "scram-sha-512")] ScramSha512 { #[serde(rename = "username")] username: Option, + #[serde(rename = "password")] password: Option, }, + #[serde(rename = "aws")] AWS { #[serde(rename = "authorizationIdentity")] #[serde(alias = "authorization_identity")] authorization_identity: Option, + #[serde(rename = "accessKeyId")] #[serde(alias = "name")] access_key_id: Option, + #[serde(rename = "secretAccessKey")] #[serde(alias = "name")] secret_access_key: Option, + #[serde(alias = "name")] #[serde(rename = "sessionToken")] session_token: Option, }, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub enum HttpMethod { - GET, - POST, - PUT, - PATCH, - DELETE, - HEAD, - OPTIONS, -} - #[serde_inline_default] #[skip_serializing_none] #[serde_alias(SnakeCase)] #[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct MonitorCommon { #[serde(rename = "id")] #[serde_as(as = "Option")] pub id: Option, + #[serde(rename = "name")] - pub name: String, + pub name: Option, + #[serde(rename = "interval")] #[serde_inline_default(Some(60))] #[serde_as(as = "Option")] pub interval: Option, + #[serde(rename = "active")] #[serde_inline_default(None)] #[serde_as(as = "Option")] pub active: Option, + #[serde(rename = "maxretries")] #[serde_as(as = "Option")] pub max_retries: Option, + #[serde(rename = "retryInterval")] #[serde_inline_default(Some(60))] #[serde_as(as = "Option")] pub retry_interval: Option, + #[serde(rename = "upsideDown")] #[serde_as(as = "Option")] pub upside_down: Option, + #[serde(rename = "parent")] #[serde_as(as = "Option")] pub parent: Option, + #[serde(rename = "group")] #[serde(skip_serializing)] pub group: Option, + #[serde(rename = "tags")] #[serde(skip_serializing_if = "Vec::is_empty")] #[serde(default)] pub tags: Vec, + #[serde(rename = "notificationIDList")] pub notification_id_list: Option>, + #[serde(rename = "accepted_statuscodes")] #[serde_inline_default(vec!["200-299".to_owned()])] pub accepted_statuscodes: Vec, } +#[skip_serializing_none] +#[serde_alias(SnakeCase)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorDatabase { + #[serde(rename = "databaseConnectionString")] + database_connection_string: Option, +} + +#[serde_inline_default] +#[skip_serializing_none] +#[serde_alias(SnakeCase)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorDns { + #[serde(rename = "hostname")] + hostname: Option, + + #[serde(rename = "dns_resolve_server")] + #[serde_inline_default(Some("1.1.1.1".to_owned()))] + dns_resolve_server: Option, + + #[serde(rename = "port")] + port: Option, + + #[serde(rename = "dns_resolve_type")] + #[serde_inline_default(Some(DnsResolverType::A))] + dns_resolve_type: Option, +} + +#[skip_serializing_none] +#[serde_alias(SnakeCase)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorDocker { + #[serde(rename = "docker_container")] + docker_container: Option, + + #[serde(rename = "docker_host")] + docker_host: Option, +} + +#[skip_serializing_none] +#[serde_alias(SnakeCase)] +#[serde_as] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorGameDig { + #[serde(rename = "game")] + game: Option, + + #[serde(rename = "hostname")] + hostname: Option, + + #[serde(rename = "port")] + port: Option, + + #[serde(rename = "gamedigGivenPortOnly")] + #[serde_as(as = "Option")] + gamedig_given_port_only: Option, +} + +#[serde_inline_default] +#[skip_serializing_none] +#[serde_alias(SnakeCase)] +#[serde_as] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorGrpcKeyword { + #[serde_as(as = "Option")] + invert_keyword: Option, + + #[serde(rename = "grpcUrl")] + grpc_url: Option, + + #[serde(rename = "maxredirects")] + #[serde_inline_default(Some(10))] + #[serde_as(as = "Option")] + max_redirects: Option, + + #[serde(rename = "grpcEnableTls")] + #[serde_as(as = "Option")] + grpc_enable_tls: Option, + + #[serde(rename = "grpcServiceName")] + grpc_service_name: Option, + + #[serde(rename = "grpcMethod")] + grpc_method: Option, + + #[serde(rename = "grpcProtobuf")] + grpc_protobuf: Option, + + #[serde(rename = "grpcBody")] + grpc_body: Option, + + #[serde(rename = "grpcMetadata")] + grpc_metadata: Option, +} + #[serde_inline_default] #[skip_serializing_none] #[serde_alias(SnakeCase)] #[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct MonitorHttp { #[serde(rename = "url")] - pub url: String, + pub url: Option, + #[serde(rename = "timeout")] #[serde_inline_default(Some(48))] #[serde_as(as = "Option")] pub timeout: Option, + #[serde(rename = "resendInterval")] #[serde_as(as = "Option")] pub resend_interval: Option, + #[serde(rename = "expiryNotification")] #[serde_as(as = "Option")] pub expiry_notification: Option, + #[serde(rename = "ignoreTls")] #[serde_as(as = "Option")] pub ignore_tls: Option, + #[serde(rename = "maxredirects")] #[serde_as(as = "Option")] pub max_redirects: Option, + #[serde(rename = "proxyId")] pub proxy_id: Option, + #[serde(rename = "method")] #[serde_inline_default(Some(HttpMethod::GET))] pub method: Option, + #[serde(rename = "httpBodyEncoding")] pub http_body_encoding: Option, + #[serde(rename = "body")] pub body: Option, + #[serde(rename = "headers")] pub headers: Option, + #[serde(rename = "authMethod")] pub auth_method: Option, + #[serde(rename = "tlsCert")] pub tls_cert: Option, + #[serde(rename = "tlsKey")] pub tls_key: Option, + #[serde(rename = "tlsCa")] pub tls_ca: Option, + #[serde(rename = "oauth_auth_method")] pub oauth_auth_method: Option, + #[serde(rename = "oauth_client_id")] pub oauth_client_id: Option, + #[serde(rename = "oauth_token_url")] pub oauth_token_url: Option, + #[serde(rename = "oauth_client_secret")] pub oauth_client_secret: Option, + #[serde(rename = "oauth_scopes")] pub oauth_scopes: Option, + #[serde(rename = "basic_auth_user")] pub basic_auth_user: Option, + #[serde(rename = "basic_auth_pass")] pub basic_auth_pass: Option, + #[serde(rename = "authDomain")] pub auth_domain: Option, + #[serde(rename = "authWorkstation")] pub auth_workstation: Option, } #[skip_serializing_none] #[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorPort { - #[serde(rename = "hostname")] - hostname: String, - #[serde(rename = "port")] - port: String, -} - -#[serde_inline_default] -#[skip_serializing_none] -#[serde_alias(SnakeCase)] -#[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorPing { - #[serde(rename = "hostname")] - hostname: String, - #[serde(rename = "packetSize")] - #[serde_inline_default(56)] - packet_size: i32, -} - -#[skip_serializing_none] -#[serde_alias(SnakeCase)] -#[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorKeyword { - #[serde(rename = "keyword")] - keyword: String, - #[serde(rename = "invertKeyword")] - #[serde_as(as = "Option")] - invert_keyword: Option, -} - -#[skip_serializing_none] -#[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct MonitorJsonQuery { #[serde(rename = "jsonPath")] json_path: Option, + #[serde(rename = "expectedValue")] expected_value: Option, } -#[serde_inline_default] #[skip_serializing_none] #[serde_alias(SnakeCase)] #[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorGrpcKeyword { - #[serde_as(as = "Option")] - invert_keyword: Option, - #[serde(rename = "grpcUrl")] - grpc_url: String, - #[serde(rename = "maxredirects")] - #[serde_inline_default(10)] - max_redirects: i32, - #[serde(rename = "grpcEnableTls")] - #[serde_as(as = "Option")] - grpc_enable_tls: Option, - #[serde(rename = "grpcServiceName")] - grpc_service_name: String, - #[serde(rename = "grpcMethod")] - grpc_method: String, - #[serde(rename = "grpcProtobuf")] - grpc_protobuf: Option, - #[serde(rename = "grpcBody")] - grpc_body: Option, - #[serde(rename = "grpcMetadata")] - grpc_metadata: Option, -} +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorKafkaProducer { + #[serde(rename = "kafkaProducerBrokers")] + kafka_producer_brokers: Vec, -#[serde_inline_default] -#[skip_serializing_none] -#[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorDns { - #[serde(rename = "hostname")] - hostname: String, - #[serde(rename = "dns_resolve_server")] - #[serde_inline_default("1.1.1.1".to_owned())] - dns_resolve_server: String, - #[serde(rename = "port")] - port: String, - #[serde(rename = "dns_resolve_type")] - #[serde_inline_default(DnsResolverType::A)] - dns_resolve_type: DnsResolverType, -} + #[serde(rename = "kafkaProducerTopic")] + kafka_producer_topic: Option, -#[skip_serializing_none] -#[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorDocker { - #[serde(rename = "docker_container")] - docker_container: String, - #[serde(rename = "docker_host")] - docker_host: String, -} + #[serde(rename = "kafkaProducerMessage")] + kafka_producer_message: Option, -#[skip_serializing_none] -#[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorRealBrowser { - #[serde(rename = "url")] - url: String, - #[serde(rename = "remoteBrowsersToggle")] + #[serde(rename = "kafkaProducerSsl")] #[serde_as(as = "Option")] - remote_browsers_toggle: Option, - #[serde(rename = "remote_browser")] - remote_browser: Option, -} + kafka_producer_ssl: Option, -#[skip_serializing_none] -#[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorPush { - #[serde(rename = "pushURL")] - push_url: Option, -} + #[serde(rename = "kafkaProducerAllowAutoTopicCreation")] + #[serde_as(as = "Option")] + kafka_producer_allow_auto_topic_creation: Option, -#[skip_serializing_none] -#[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorSteam { - #[serde(rename = "hostname")] - hostname: String, - #[serde(rename = "port")] - port: String, + #[serde(rename = "kafkaProducerSaslOptions")] + kafka_producer_sasl_options: Option, } #[skip_serializing_none] #[serde_alias(SnakeCase)] #[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorGameDig { - #[serde(rename = "game")] - game: String, - #[serde(rename = "hostname")] - hostname: String, - #[serde(rename = "port")] - port: String, - #[serde(rename = "gamedigGivenPortOnly")] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorKeyword { + #[serde(rename = "keyword")] + keyword: Option, + + #[serde(rename = "invertKeyword")] #[serde_as(as = "Option")] - gamedig_given_port_only: Option, + invert_keyword: Option, } #[serde_inline_default] #[skip_serializing_none] #[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct MonitorMqtt { #[serde(rename = "hostname")] - hostname: String, + hostname: Option, + #[serde(rename = "port")] - port: String, + port: Option, + #[serde(rename = "mqttUsername")] mqtt_username: Option, + #[serde(rename = "mqttPassword")] mqtt_password: Option, + #[serde(rename = "mqttTopic")] - mqtt_topic: String, + mqtt_topic: Option, + #[serde(rename = "mqttCheckType")] mqtt_check_type: Option, + #[serde(rename = "mqttSuccessMessage")] mqtt_success_message: Option, } +#[serde_inline_default] #[skip_serializing_none] #[serde_alias(SnakeCase)] #[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorKafkaProducer { - #[serde(rename = "kafkaProducerBrokers")] - kafka_producer_brokers: Option, - #[serde(rename = "kafkaProducerTopic")] - kafka_producer_topic: Option, - #[serde(rename = "kafkaProducerMessage")] - kafka_producer_message: Option, - #[serde(rename = "kafkaProducerSsl")] - #[serde_as(as = "Option")] - kafka_producer_ssl: Option, - #[serde(rename = "kafkaProducerAllowAutoTopicCreation")] - #[serde_as(as = "Option")] - kafka_producer_allow_auto_topic_creation: Option, +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorPing { + #[serde(rename = "hostname")] + hostname: Option, + + #[serde(rename = "packetSize")] + #[serde_inline_default(Some(56))] + #[serde_as(as = "Option")] + packet_size: Option, } #[skip_serializing_none] #[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] -pub struct MonitorDatabase { - #[serde(rename = "databaseConnectionString")] - database_connection_string: Option, +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorPort { + #[serde(rename = "hostname")] + hostname: Option, + + #[serde(rename = "port")] + port: Option, +} + +#[skip_serializing_none] +#[serde_alias(SnakeCase)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorPush { + #[serde(rename = "pushURL")] + push_url: Option, } #[skip_serializing_none] #[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct MonitorRadius { #[serde(rename = "hostname")] hostname: Option, + #[serde(rename = "port")] port: Option, + #[serde(rename = "radiusUsername")] - radius_username: String, + radius_username: Option, + #[serde(rename = "radiusPassword")] - radius_password: String, + radius_password: Option, + #[serde(rename = "radiusSecret")] - radius_secret: String, + radius_secret: Option, + #[serde(rename = "radiusCalledStationId")] - radius_called_station_id: String, + radius_called_station_id: Option, + #[serde(rename = "radiusCallingStationId")] - radius_calling_station_id: String, + radius_calling_station_id: Option, +} + +#[skip_serializing_none] +#[serde_as] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorRealBrowser { + #[serde(rename = "url")] + url: Option, + + #[serde(rename = "remoteBrowsersToggle")] + #[serde_as(as = "Option")] + remote_browsers_toggle: Option, + + #[serde(rename = "remote_browser")] + remote_browser: Option, +} + +#[skip_serializing_none] +#[serde_alias(SnakeCase)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MonitorSteam { + #[serde(rename = "hostname")] + hostname: Option, + + #[serde(rename = "port")] + port: Option, } #[skip_serializing_none] #[serde_alias(SnakeCase)] -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct MonitorTailscale { #[serde(rename = "hostname")] - hostname: String, + hostname: Option, } -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub enum Monitor { #[serde(rename = "group")] @@ -484,154 +616,199 @@ pub enum Monitor { #[serde(flatten)] common: MonitorCommon, }, + #[serde(rename = "http")] Http { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] http: MonitorHttp, }, + #[serde(rename = "port")] Port { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] port: MonitorPort, }, + #[serde(rename = "ping")] Ping { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] ping: MonitorPing, }, + #[serde(rename = "keyword")] Keyword { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] http: MonitorHttp, + #[serde(flatten)] keyword: MonitorKeyword, }, + #[serde(rename = "json-query")] JsonQuery { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] http: MonitorHttp, + #[serde(flatten)] json_query: MonitorJsonQuery, }, + #[serde(rename = "grpc-keyword")] GrpcKeyword { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] keyword: MonitorKeyword, + #[serde(flatten)] grpc_keyword: MonitorGrpcKeyword, }, + #[serde(rename = "dns")] Dns { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] dns: MonitorDns, }, + #[serde(rename = "docker")] Docker { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] docker: MonitorDocker, }, + #[serde(rename = "real-browser")] RealBrowser { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] real_browser: MonitorRealBrowser, }, + #[serde(rename = "push")] Push { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] push: MonitorPush, }, + #[serde(rename = "steam")] Steam { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] steam: MonitorSteam, }, + #[serde(rename = "gamedig")] GameDig { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] gamedig: MonitorGameDig, }, + #[serde(rename = "mqtt")] Mqtt { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] mqtt: MonitorMqtt, }, + #[serde(rename = "kafka-producer")] KafkaProducer { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] kafka_producer: MonitorKafkaProducer, }, + #[serde(rename = "sqlserver")] SqlServer { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] database: MonitorDatabase, }, + #[serde(rename = "postgres")] Postgres { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] database: MonitorDatabase, }, + #[serde(rename = "mysql")] Mysql { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] database: MonitorDatabase, + #[serde(rename = "radiusPassword")] password: Option, }, + #[serde(rename = "mongodb")] Mongodb { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] database: MonitorDatabase, }, + #[serde(rename = "radius")] Radius { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] radius: MonitorRadius, }, + #[serde(rename = "redis")] Redis { #[serde(flatten)] common: MonitorCommon, + #[serde(flatten)] database: MonitorDatabase, }, + #[serde(rename = "tailscale-ping")] TailscalePing { #[serde(flatten)] @@ -721,29 +898,5 @@ impl Monitor { } } -#[skip_serializing_none] -#[serde_alias(SnakeCase)] -#[serde_as] -#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq)] -pub struct Tag { - #[serde_as(as = "Option")] - pub id: Option, - pub name: String, - pub color: String, - #[serde_as(as = "Option")] - pub tag_id: Option, - pub value: Option, -} - -// #[derive(Debug, Serialize, Deserialize, Default)] -// pub struct MonitorList { -// monitors: Vec, -// } pub type MonitorList = HashMap; - -// #[serde_alias(SnakeCase)] -// #[derive(Debug, Serialize, Deserialize, Clone)] -// pub struct TagList { -// pub tags: Vec, -// } pub type TagList = Vec; diff --git a/src/sync.rs b/src/sync.rs index 20f97a4..d90dad8 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -49,7 +49,7 @@ impl Sync { let config = vec![("type".to_owned(), monitor_type.to_owned())] .into_iter() .chain(settings.into_iter()) - .map(|(key, value)| format!("{} = \"{}\"", key, value)) + .map(|(key, value)| format!("{} = {}", key, toml::Value::String(value))) .join("\n"); if let Ok(toml) = toml::from_str::(&config) { @@ -120,13 +120,13 @@ impl Sync { .tags() .await .into_iter() - .find(|tag| tag.name == self.config.kuma.tag_name) + .find(|tag| tag.name.as_deref() == Some(&self.config.kuma.tag_name)) { Some(tag) => tag, None => { kuma.add_tag(Tag { - name: self.config.kuma.tag_name.clone(), - color: self.config.kuma.tag_color.clone(), + name: Some(self.config.kuma.tag_name.clone()), + color: Some(self.config.kuma.tag_color.clone()), ..Default::default() }) .await @@ -143,7 +143,7 @@ impl Sync { .common() .tags .iter() - .filter(|tag| tag.name == self.config.kuma.tag_name) + .filter(|tag| tag.name.as_deref() == Some(&self.config.kuma.tag_name)) .find_map(|tag| tag.value.as_ref()) { Some(id) => Some((id.to_owned(), monitor)),