From 3acc97e6f5d4d69e001658a05c7b28b157a633fa Mon Sep 17 00:00:00 2001 From: linxside <39219399+linxside@users.noreply.github.com> Date: Sat, 13 Jul 2024 13:26:37 +0200 Subject: [PATCH] Revert nats jetstream (#401) * Revert "fix: make nats consumer durable with cleanup after one week (#363)" This reverts commit 824712b80877d0d19b27a6fa3f31ae31206d984c. * Revert "fix: consumer listener and topic (#362)" This reverts commit 4d938fb8cf97f2a86f601728b1f6d8375c40eb87. * Revert "fix: use unique consumer id (#361)" This reverts commit c79800c83128ee5db4e887043dbfa58349a9f517. * Revert "test: remove duplicate mocks (#345)" This reverts commit 2e39e84e102e8472dfc7a887a2c7347658b7c67e. * Revert "BREAKING CHANGE: Remove consul as dependency and replacing it by nats jetstream (#342)" This reverts commit f7eafc25 --- .golangci.yml | 4 +- README.md | 13 +- .../config/pdns-api-proxy/config.toml | 6 + .../config/pdns-health-checker/config.toml | 8 +- .../config/pdns-secondary-syncer/config.toml | 10 +- .../config/pdns-zone-provider/config.toml | 10 +- cmd/example-microservice/main.go | 4 +- configs/example-microservice/config.toml | 6 + configs/pdns-api-proxy/config.toml | 6 + configs/pdns-health-checker/config.toml | 8 +- configs/pdns-secondary-syncer/config.toml | 8 +- configs/pdns-zone-provider/config.toml | 8 +- container-compose.yaml => docker-compose.yaml | 22 +- docs/development/release.md | 5 +- docs/development/test.md | 5 +- docs/index.md | 26 +- docs/mermaid/event_health_check.mmd | 8 +- docs/mermaid/health_check.mmd | 8 +- docs/microservices/pdns-api-proxy.md | 3 +- docs/microservices/pdns-health-checker.md | 2 +- docs/microservices/pdns-secondary-syncer.md | 2 +- docs/operation/configuration.md | 32 +- docs/operation/installation.md | 16 +- docs/operation/observability.md | 2 +- go.mod | 19 +- go.sum | 219 ++++++- .../internalserviceproxy.go | 9 +- .../healthchecks/checks.go | 3 +- .../healthchecks/eventcheck/eventcheck.go | 57 +- .../intervallcheck/intervallcheck.go | 7 +- .../intervallsigningsync.go | 7 +- .../healthchecks/utils/utils.go | 14 +- .../healthorchestrator/healthorchestrator.go | 27 +- .../pdns-health-checker/models/modelstate.go | 8 +- .../servicediscovery/servicediscovery.go | 8 +- .../eventlistener/eventlistener.go | 116 ++-- .../modeljob/modeljob.go | 4 +- .../powerdns/powerdns.go | 27 +- .../primaryzoneprovider/primary.go | 4 +- .../pdns-secondary-syncer/worker/worker.go | 2 +- .../pdns-zone-provider/messaging/messaging.go | 6 +- internal/pkg/eventutils/eventutils.go | 12 +- internal/pkg/httputils/httputils_test.go | 12 +- internal/pkg/mocks/jetstream.go | 585 ------------------ .../mocks/jetstream_consumer_info_listener.go | 68 -- internal/pkg/mocks/jetstream_stream.go | 274 -------- pkg/microservice/messaging/messaging.go | 146 ++--- pkg/microservice/messaging/nats.go | 201 ------ pkg/microservice/messaging/nats_test.go | 155 ----- pkg/microservice/microservice.go | 58 +- pkg/microservice/servicediscovery/errors.go | 7 + .../servicediscovery/servicediscovery.go | 296 +++++++++ .../servicediscovery/servicediscovery_test.go | 155 +++++ .../servicediscovery/serviceregistration.go | 50 ++ .../serviceregistration_test.go | 102 +++ 55 files changed, 1242 insertions(+), 1638 deletions(-) rename container-compose.yaml => docker-compose.yaml (86%) delete mode 100644 internal/pkg/mocks/jetstream.go delete mode 100644 internal/pkg/mocks/jetstream_consumer_info_listener.go delete mode 100644 internal/pkg/mocks/jetstream_stream.go delete mode 100644 pkg/microservice/messaging/nats.go delete mode 100644 pkg/microservice/messaging/nats_test.go create mode 100644 pkg/microservice/servicediscovery/errors.go create mode 100644 pkg/microservice/servicediscovery/servicediscovery.go create mode 100644 pkg/microservice/servicediscovery/servicediscovery_test.go create mode 100644 pkg/microservice/servicediscovery/serviceregistration.go create mode 100644 pkg/microservice/servicediscovery/serviceregistration_test.go diff --git a/.golangci.yml b/.golangci.yml index 34c8193a..85ade0e1 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -32,11 +32,9 @@ linters: - dupl - exportloopref - govet - disable: - - errcheck + disable-all: false presets: - bugs - - format - unused - complexity - performance diff --git a/README.md b/README.md index f577536b..5f8ab32b 100644 --- a/README.md +++ b/README.md @@ -27,16 +27,21 @@ Microservices: - contains zone information - Nx secondary (public authoritative nameserver) - serves zone data -- Nx nats with jetstream (message broker) - - complete communication between microservices will use handled by broker +- Nx consul (service discovery) - used for discovering active healthy secondaries - healthchecks - - after a defined interval without a ping a secondary will be marked as inactive + - every microservice pings consul in a configurable interval + - after three times interval without a ping from a microservice, this service will be unhealthy + - after ten times interval without a ping the service will be deregistered + - if the systemload is greater than 10 the service will be in a warn state +- Nx nats (message broker) + - complete communication between microservices will use handled by broker ## Techstack * written in Go -* NATS as Message Broker +* Consul for Service Discovery +* NATS as Message Broker for the biggest amount of communication ## Dependencies diff --git a/build/ci/services/config/pdns-api-proxy/config.toml b/build/ci/services/config/pdns-api-proxy/config.toml index 25fbb963..543220f9 100644 --- a/build/ci/services/config/pdns-api-proxy/config.toml +++ b/build/ci/services/config/pdns-api-proxy/config.toml @@ -12,6 +12,12 @@ DEBUG = true [Prometheus] Address = "0.0.0.0:9502" # turn off by set empty string +[ServiceDiscovery] +URL = "http://consul:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://nats:4222" Username = "" # optional diff --git a/build/ci/services/config/pdns-health-checker/config.toml b/build/ci/services/config/pdns-health-checker/config.toml index fd65c65b..03df4762 100644 --- a/build/ci/services/config/pdns-health-checker/config.toml +++ b/build/ci/services/config/pdns-health-checker/config.toml @@ -10,6 +10,12 @@ DEBUG = true [Prometheus] Address = "0.0.0.0:9501" # turn off by set empty string +[ServiceDiscovery] +URL = "http://consul:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://nats:4222" Username = "" # optional @@ -26,7 +32,7 @@ Mod = "zone.modified" Del = "zone.delete" [ZoneStateTopics] -Prefix = "zonestate.>" +Prefix = "zonestate." [HealthChecks] EventCheckWaitTime = "20s" diff --git a/build/ci/services/config/pdns-secondary-syncer/config.toml b/build/ci/services/config/pdns-secondary-syncer/config.toml index 4299e054..431a1797 100644 --- a/build/ci/services/config/pdns-secondary-syncer/config.toml +++ b/build/ci/services/config/pdns-secondary-syncer/config.toml @@ -10,6 +10,12 @@ DEBUG = true [Prometheus] Address = "0.0.0.0:9503" # turn off by set empty string +[ServiceDiscovery] +URL = "http://consul:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://nats:4222" Username = "" # optional @@ -23,7 +29,7 @@ EventDelay = "0s" APIWorker = 4 [AXFRPrimary] -Address = "10.89.1.54:20102" +Address = "0.0.0.0:20102" [ZoneEventTopics] Add = "zone.add" @@ -34,4 +40,4 @@ Del = "zone.delete" Prefix = "zonedata." [ZoneStateTopics] -Prefix = "zonestate.>" \ No newline at end of file +Prefix = "zonestate." \ No newline at end of file diff --git a/build/ci/services/config/pdns-zone-provider/config.toml b/build/ci/services/config/pdns-zone-provider/config.toml index 1e507187..a9452991 100644 --- a/build/ci/services/config/pdns-zone-provider/config.toml +++ b/build/ci/services/config/pdns-zone-provider/config.toml @@ -10,6 +10,12 @@ DEBUG = true [Prometheus] Address = "0.0.0.0:9500" # turn off by set empty string +[ServiceDiscovery] +URL = "http://consul:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://nats:4222" Username = "" # optional @@ -20,7 +26,7 @@ URL = "http://pdns-primary:8081" APIToken = "0000" ServerID = "localhost" AXFRTimeout = "2s" -AXFRAddress = "pdns-primary:5301" +AXFRAddress = "127.0.0.1:53" [ZoneDataTopics] -Wildcard = "zonedata.>" \ No newline at end of file +Wildcard = "zonedata.*" \ No newline at end of file diff --git a/cmd/example-microservice/main.go b/cmd/example-microservice/main.go index 5ae1fcdb..c00869af 100644 --- a/cmd/example-microservice/main.go +++ b/cmd/example-microservice/main.go @@ -40,9 +40,7 @@ func main() { go startHealthServiceEndpoint(xd) - if err := xd.MessageBroker.SubscribeAsync("test.test", waitformessage); err != nil { - logger.FatalErrLog(err) - } + xd.MessageBroker.SubscribeAsync("test.test", waitformessage) servutils.WaitToShutdownServer(&xd, func() { closeMicroservice(xd) diff --git a/configs/example-microservice/config.toml b/configs/example-microservice/config.toml index d385c7e2..862b39c2 100644 --- a/configs/example-microservice/config.toml +++ b/configs/example-microservice/config.toml @@ -12,6 +12,12 @@ DEBUG = true [Prometheus] Address = "localhost:9499" # turn off by set empty string +[ServiceDiscovery] +URL = "http://localhost:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional diff --git a/configs/pdns-api-proxy/config.toml b/configs/pdns-api-proxy/config.toml index 12602dd4..8b4a6030 100644 --- a/configs/pdns-api-proxy/config.toml +++ b/configs/pdns-api-proxy/config.toml @@ -12,6 +12,12 @@ DEBUG = true [Prometheus] Address = "localhost:9502" # turn off by set empty string +[ServiceDiscovery] +URL = "http://localhost:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional diff --git a/configs/pdns-health-checker/config.toml b/configs/pdns-health-checker/config.toml index 1331fce7..a4d30964 100644 --- a/configs/pdns-health-checker/config.toml +++ b/configs/pdns-health-checker/config.toml @@ -10,6 +10,12 @@ DEBUG = true [Prometheus] Address = "localhost:9501" # turn off by set empty string +[ServiceDiscovery] +URL = "http://localhost:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional @@ -26,7 +32,7 @@ Mod = "zone.modified" Del = "zone.delete" [ZoneStateTopics] -Prefix = "zonestate.>" +Prefix = "zonestate." [HealthChecks] EventCheckWaitTime = "20s" diff --git a/configs/pdns-secondary-syncer/config.toml b/configs/pdns-secondary-syncer/config.toml index faa9b248..d8e0ff66 100644 --- a/configs/pdns-secondary-syncer/config.toml +++ b/configs/pdns-secondary-syncer/config.toml @@ -10,6 +10,12 @@ DEBUG = true [Prometheus] Address = "localhost:9503" # turn off by set empty string +[ServiceDiscovery] +URL = "http://localhost:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional @@ -34,4 +40,4 @@ Del = "zone.delete" Prefix = "zonedata." [ZoneStateTopics] -Prefix = "zonestate.>" \ No newline at end of file +Prefix = "zonestate." \ No newline at end of file diff --git a/configs/pdns-zone-provider/config.toml b/configs/pdns-zone-provider/config.toml index d6c62587..c4fbad61 100644 --- a/configs/pdns-zone-provider/config.toml +++ b/configs/pdns-zone-provider/config.toml @@ -10,6 +10,12 @@ DEBUG = true [Prometheus] Address = "localhost:9500" # turn off by set empty string +[ServiceDiscovery] +URL = "http://localhost:8500" +HealthPingIntervall = "5s" +Username = "" # optional +Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional @@ -23,4 +29,4 @@ AXFRTimeout = "2s" AXFRAddress = "127.0.0.1:53" [ZoneDataTopics] -Wildcard = "zonedata.>" \ No newline at end of file +Wildcard = "zonedata.*" \ No newline at end of file diff --git a/container-compose.yaml b/docker-compose.yaml similarity index 86% rename from container-compose.yaml rename to docker-compose.yaml index 76c3c301..79f926aa 100644 --- a/container-compose.yaml +++ b/docker-compose.yaml @@ -31,8 +31,7 @@ services: depends_on: - pdns-secondary networks: - pdns-distribute-net: - ipv4_address: 10.89.1.54 + - pdns-distribute-net ports: - "9503:9503" pdns-zone-provider: @@ -43,8 +42,7 @@ services: depends_on: - pdns-secondary networks: - pdns-distribute-net: - ipv4_address: 10.89.1.55 + - pdns-distribute-net ports: - "9500:9500" pdns-primary: @@ -52,6 +50,7 @@ services: context: ./build/ci/pdns-primary dockerfile: Containerfile depends_on: + - consul - nats networks: - pdns-distribute-net @@ -63,14 +62,22 @@ services: context: ./build/ci/pdns-secondary dockerfile: Containerfile depends_on: + - consul - nats networks: - pdns-distribute-net ports: - "5300:53" - "8082:8082" + consul: + image: docker.io/hashicorp/consul:1.17.2 + networks: + - pdns-distribute-net + ports: + - "8500:8500" + - "8501:8501" nats: - image: docker.io/library/nats:2.10.11 + image: docker.io/library/nats:2.10.10 command: ["--config", "nats-server.conf", "--jetstream", "--server_name", "nats-js-test", "--routes", "nats://ruser:T0pS3cr3t@nats2:6223"] networks: - pdns-distribute-net @@ -78,7 +85,7 @@ services: - "4222:4222" - "8222:8222" nats2: - image: docker.io/library/nats:2.10.11 + image: docker.io/library/nats:2.10.10 command: ["--config", "nats-server.conf", "--jetstream", "--server_name", "nats-js-test2", "--routes", "nats://ruser:T0pS3cr3t@nats:6222", "--port", "4223", "--http_port", "8223", "--cluster", "nats://nats2:6223"] networks: - pdns-distribute-net @@ -88,6 +95,3 @@ services: networks: pdns-distribute-net: enable_ipv6: false - ipam: - config: - - subnet: 10.89.1.0/24 diff --git a/docs/development/release.md b/docs/development/release.md index f56efe94..0b2e161a 100644 --- a/docs/development/release.md +++ b/docs/development/release.md @@ -18,14 +18,15 @@ make snapshot-release ```git git describe --tags --abbrev=0 ``` -1. Increment the version, create the tag and push to main repository. Commit tags use the format + +2. Increment the version, create the tag and push to main repository. Commit tags use the format [Semantic Versioning](https://semver.org/). The tag description can be the semantic version. ```git git tag -a v0.0.0 -m "v0.0.0" git push ``` -1. Build release. +3. Build release. !!! caution The build and deployment of the production release / binaries is part of the GitHub pipeline. diff --git a/docs/development/test.md b/docs/development/test.md index cc545a3d..d9758120 100644 --- a/docs/development/test.md +++ b/docs/development/test.md @@ -5,10 +5,13 @@ The local test environment consist of one container per pdns-distribute microser *Container Overview:* +??? note "consul" +The service discovery tool consul exposes the ports 8500 and 8501 to the host. Consul runs in standalone mode. ??? note "nats" The message broker service nats exposes the ports 4222 and 8222 to the host. Nats runs in cluster mode. Every service connects to this nats instance. ??? note "nats2" - The message broker service nats exposes the ports 4223 and 8223 to the host. This instance is part of the two node cluster which is necessary to activate jetstream and has no other function. +The message broker service nats exposes the ports 4223 and 8223 to the host. This instance is part of the two node +cluster which is necessary to activate Jetstream and has no other function. ??? note "pdns-primary" This container contains a powerdns server with a sqlite3 database as backend. It is the source of zonedata for the synchronization process. This container exposes port 8081 for the api and port 5301 for DNS (like port 53). diff --git a/docs/index.md b/docs/index.md index 92cd5f3a..633ee0ed 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,14 +11,14 @@ features. ## Features * event based architecture (hidden primary, public secondary) for fast and scalable sync -* self-healing of outdated secondaries +* self healing of outdated secondaries * message driven * most events parallelized * easy deployment by providing .deb packages and systemd configs for automatic restart * security by keeping it simple -* security: transport encryption with by nats +* security: and encryption provided by consul and nats * security: secondaries doesn't have dnssec private keys -* security: if system load is too high the health check will be show a warning +* security: if system load is too high the health check will be show an warning * full ipv6 support (ipv4 is optional) * self-healing @@ -40,31 +40,37 @@ Microservices: ## Architecture - 1x primary (internal data management) - - clients can use the primary through the powerdns api + - clients can using the primary through the powerdns api - contains zone information - Nx secondary (public authoritative nameserver) - serves zone data -- Nx nats with jetstream (message broker) - - complete communication between microservices will use handled by broker +- Nx consul (service discovery) - used for discovering active healthy secondaries - healthchecks - - after a defined interval without a ping a secondary will be marked as inactive + - every microservice pings consul in a configurable interval + - after three times interval without a ping from a microservice, this service will be unhealthy + - after ten times interval without a ping the service will be deregistered + - if the systemload is greater than 10 the service will be in a warn state +- Nx nats (message broker) + - complete communication between microservices will use handled by broker ### Security Sensitive data for dnssec signing is kept only on the primary server. The signed zone data - without the secret keys - will be -transferred to every secondary server. All microservices will connect to nats, it's responsible for secure access +transferred to every secondary server. All microservices will connect to consul and nats, they are responsible for +secure access to the infrastructure and encryption of server to server connections. This has the advantage of not having to care about certificates for each microservice. ## Techstack * written in Go -* NATS as Message Broker +* Consul for Service Discovery +* NATS as Message Broker for the biggest amount of communication ## Dependencies -* go (>= 1.22) +* go (>= 1.17) * podman * golangci-lint * goreleaser diff --git a/docs/mermaid/event_health_check.mmd b/docs/mermaid/event_health_check.mmd index 2b2dfcd7..8b749b6a 100644 --- a/docs/mermaid/event_health_check.mmd +++ b/docs/mermaid/event_health_check.mmd @@ -2,16 +2,18 @@ sequenceDiagram participant a as health-checker participant b as [Primary PowerDNS API] participant c as [Message Broker] +participant d as [Service Discovery] participant e as [Secondary PowerDNS] c-xa: {Zone.Add} or {Zone.Change} a->>+b: Get-Zone-Serial b-->>-a: Zone-Serial -a->>+c: Get-Active-Secondaries -c-->>-a: Active-Secondaries +a->>+d: Get-Active-Secondaries +d-->>-a: Active-Secondaries loop All Secondaries a->>+e: Get-Zone-Serial e-->>-a: Zone-Serial end a-xc: {Zone.Change} -Note over a,c: pdns-primary +Note over a,b: pdns-primary +Note over c,d: pdns-primary Note over e: pdns-secondary \ No newline at end of file diff --git a/docs/mermaid/health_check.mmd b/docs/mermaid/health_check.mmd index 7fe12d10..fb4e698b 100644 --- a/docs/mermaid/health_check.mmd +++ b/docs/mermaid/health_check.mmd @@ -2,12 +2,13 @@ sequenceDiagram participant a as health-checker participant b as [Primary PowerDNS API] participant c as [Message Broker] +participant d as [Service Discovery] participant e as [Secondary PowerDNS] loop Every Quarter of an hour a->>+b: Get-Zones-Serial b-->>-a: All-Zones-Serial -a->>+c: Get-Active-Secondaries -c-->>-a: Active-Secondaries +a->>+d: Get-Active-Secondaries +d-->>-a: Active-Secondaries loop All Secondaries loop All Zones a->>+e: Get-Zone-Serial @@ -16,5 +17,6 @@ end end a-xc: {Zone.Change} end -Note over a,c: pdns-primary +Note over a,b: pdns-primary +Note over c,d: pdns-primary Note over e: pdns-secondary \ No newline at end of file diff --git a/docs/microservices/pdns-api-proxy.md b/docs/microservices/pdns-api-proxy.md index d55d5406..3efc3be0 100644 --- a/docs/microservices/pdns-api-proxy.md +++ b/docs/microservices/pdns-api-proxy.md @@ -1,6 +1,7 @@ # pdns-api-proxy The api proxy sits in front of the powerdns primary api. It will generate zone events from api interaction with the -primary api and publish them by using the distributed message broker nats. The microservice will automatically create self-signed certificates for the exposed api listener, +primary api and publish them by using the distributed message broker nats. The microservice will automatically create +self signed certificates for the exposed api listener, if no certificate will be [configured](../operation/configuration.md). ## Workflows diff --git a/docs/microservices/pdns-health-checker.md b/docs/microservices/pdns-health-checker.md index ab58c0b1..c93fc9bb 100644 --- a/docs/microservices/pdns-health-checker.md +++ b/docs/microservices/pdns-health-checker.md @@ -37,5 +37,5 @@ zone event ### Workflow 5 / Get active secondaries and zones in background 1. Wait for a configurable amount of time - 1. Get active secondaries from nats as active consumers + 1. Get active healthy secondaries from Consul (Service Discovery) 2. Get active zones from powerdns primary per HTTP API diff --git a/docs/microservices/pdns-secondary-syncer.md b/docs/microservices/pdns-secondary-syncer.md index f85d068c..73f5f60c 100644 --- a/docs/microservices/pdns-secondary-syncer.md +++ b/docs/microservices/pdns-secondary-syncer.md @@ -19,4 +19,4 @@ fetching zone data. ### Workflow / Respond Zone State 1. Listen for secondary state request events (message broker) - 1. Respond the secondaries state via the message broker + 2. Respond the secondaries state via the message broker diff --git a/docs/operation/configuration.md b/docs/operation/configuration.md index 51e841e1..1ed47dbb 100644 --- a/docs/operation/configuration.md +++ b/docs/operation/configuration.md @@ -20,7 +20,13 @@ be adopted to your requirements. The packages include default configs. [Prometheus] Address = "localhost:9502" # turn off by set empty string - + + [ServiceDiscovery] + URL = "http://localhost:8500" + HealthPingIntervall = "5s" + Username = "" # optional + Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional @@ -51,6 +57,12 @@ be adopted to your requirements. The packages include default configs. [Prometheus] Address = "localhost:9501" # turn off by set empty string + [ServiceDiscovery] + URL = "http://localhost:8500" + HealthPingIntervall = "5s" + Username = "" # optional + Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional @@ -67,7 +79,7 @@ be adopted to your requirements. The packages include default configs. Del = "zone.delete" [ZoneStateTopics] - Prefix = "zonestate.>" + Prefix = "zonestate." [HealthChecks] EventCheckWaitTime = "20s" @@ -92,6 +104,12 @@ be adopted to your requirements. The packages include default configs. [Prometheus] Address = "localhost:9500" # turn off by set empty string + [ServiceDiscovery] + URL = "http://localhost:8500" + HealthPingIntervall = "5s" + Username = "" # optional + Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional @@ -105,7 +123,7 @@ be adopted to your requirements. The packages include default configs. AXFRAddress = "127.0.0.1:53" [ZoneDataTopics] - Wildcard = "zonedata.>" + Wildcard = "zonedata.*" ``` ## Secondary @@ -125,6 +143,12 @@ be adopted to your requirements. The packages include default configs. [Prometheus] Address = "localhost:9503" # turn off by set empty string + [ServiceDiscovery] + URL = "http://localhost:8500" + HealthPingIntervall = "5s" + Username = "" # optional + Password = "" # optional + [MessageBroker] URL = "nats://localhost:4222" Username = "" # optional @@ -149,5 +173,5 @@ be adopted to your requirements. The packages include default configs. Prefix = "zonedata." [ZoneStateTopics] - Prefix = "zonestate.>" + Prefix = "zonestate." ``` \ No newline at end of file diff --git a/docs/operation/installation.md b/docs/operation/installation.md index a3c7966c..0ec222fa 100644 --- a/docs/operation/installation.md +++ b/docs/operation/installation.md @@ -1,19 +1,23 @@ # Installation ## Requirements -* Actual linux based os with systemd support (e.g. Debian Bookworm) -NATS instances can be run on primaries or secondaries. The only limit is, that only one instance of each +* Actual linux based os with systemd support (eg. Debian Buster) + +NATS and Consul instances can be run on primaries or secondaries. The only limit is, that only one instance of each should be run on a system. -* NATS cluster with jetstream (message broker) +* Consul cluster (service discovery) +* NATS cluster (message broker) ### Primary -* PowerDNS >= 4.8 (with database backend) + +* PowerDNS >= 4.3 (with database backend) ### Secondaries -* PowerDNS >= 4.8 (with database backend) -* dnsdist >= 1.9 (recommended) + +* PowerDNS >= 4.3 (with database backend) +* dnsdist >= 1.5 (recommended) ## Install latest version ### Primary diff --git a/docs/operation/observability.md b/docs/operation/observability.md index fe7d7a76..49d0733d 100644 --- a/docs/operation/observability.md +++ b/docs/operation/observability.md @@ -14,7 +14,7 @@ We recommend Grafana and Prometheus for displaying and monitoring. ### Grafana Dashboard Examples ![primary-dashboard](../img/pdns-distribute-primary-dashboard.png) -![secondary-dashboard](../img/pdns-distribute-secondary-dashboard.png) +![secondary-dashboar](../img/pdns-distribute-secondary-dashboard.png) ### Prometheus Endpoints diff --git a/go.mod b/go.mod index 5fbc7575..b897efbe 100644 --- a/go.mod +++ b/go.mod @@ -4,31 +4,47 @@ go 1.22 require ( github.com/google/uuid v1.6.0 + github.com/hashicorp/consul/api v1.27.0 github.com/miekg/dns v1.1.59 github.com/mvmaasakkers/certificates v0.7.2 github.com/nats-io/nats.go v1.35.0 github.com/prometheus/client_golang v1.19.1 github.com/rs/zerolog v1.32.0 + github.com/shirou/gopsutil/v3 v3.24.1 + github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.2 github.com/stretchr/testify v1.9.0 - go.uber.org/mock v0.4.0 ) require ( + github.com/armon/go-metrics v0.4.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/fatih/color v1.14.1 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-hclog v1.5.0 // indirect + github.com/hashicorp/go-immutable-radix v1.3.1 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/go-rootcerts v1.0.2 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/hashicorp/serf v0.10.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/klauspost/compress v1.17.2 // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/nats-io/nkeys v0.4.7 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect @@ -39,6 +55,7 @@ require ( github.com/spf13/cast v1.6.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/subosito/gotenv v1.6.0 // indirect + github.com/yusufpapurcu/wmi v1.2.3 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.21.0 // indirect diff --git a/go.sum b/go.sum index 51c884e3..ae74331f 100644 --- a/go.sum +++ b/go.sum @@ -1,60 +1,200 @@ +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= +github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= +github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/consul/api v1.27.0 h1:gmJ6DPKQog1426xsdmgk5iqDyoRiNc+ipBdJOqKQFjc= +github.com/hashicorp/consul/api v1.27.0/go.mod h1:JkekNRSou9lANFdt+4IKx3Za7XY0JzzpQjEb4Ivo1c8= +github.com/hashicorp/consul/sdk v0.15.1 h1:kKIGxc7CZtflcF5DLfHeq7rOQmRq3vk7kwISN9bif8Q= +github.com/hashicorp/consul/sdk v0.15.1/go.mod h1:7pxqqhqoaPqnBnzXD1StKed62LqJeClzVsUEy85Zr0A= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= +github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= +github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= +github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= +github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= +github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= +github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4= github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mvmaasakkers/certificates v0.7.2 h1:bV3x1XewlN+OJ9ufzeqSbQlQrR+orMdQylN2Czu1MrA= github.com/mvmaasakkers/certificates v0.7.2/go.mod h1:MpmgTzKcPJnGbDdZtaz/oZ0ak40/jy1EmxKeex5tPZg= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nats-io/nats.go v1.35.0 h1:XFNqNM7v5B+MQMKqVGAyHwYhyKb48jrenXNxIU20ULk= github.com/nats-io/nats.go v1.35.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8= github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI= github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= +github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSzKKE= github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -62,63 +202,138 @@ github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncj github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic= golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw= golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/app/pdns-api-proxy/internalserviceproxy/internalserviceproxy.go b/internal/app/pdns-api-proxy/internalserviceproxy/internalserviceproxy.go index e08d2c2e..28d5bae8 100644 --- a/internal/app/pdns-api-proxy/internalserviceproxy/internalserviceproxy.go +++ b/internal/app/pdns-api-proxy/internalserviceproxy/internalserviceproxy.go @@ -19,14 +19,7 @@ var ( func StartProxy(microservice *msframe.Microservice) error { initConfig(microservice) - stream, err := ms.MessageBroker.CreatePersistentMessageStore("pdns-distribute-event-store", []string{"zone.>"}) - if err != nil { - return err - } - - ms.MessageBroker.SetStream(stream) - - err = startHTTPServer(serviceconfig) + err := startHTTPServer(serviceconfig) if err != nil { return err } diff --git a/internal/app/pdns-health-checker/healthchecks/checks.go b/internal/app/pdns-health-checker/healthchecks/checks.go index 060264c1..868e87e5 100644 --- a/internal/app/pdns-health-checker/healthchecks/checks.go +++ b/internal/app/pdns-health-checker/healthchecks/checks.go @@ -11,8 +11,7 @@ import ( ) func StartAllHealthChecks(msobject *microservice.Microservice, configobject *config.ServiceConfiguration, - actualstate *models.State, -) { + actualstate *models.State) { go eventcheck.StartEventCheckHandler(msobject, configobject, actualstate) go intervallcheck.StartPeriodicalCheck(msobject, configobject, actualstate) go intervallsigningsync.StartPeridoicalSigningSync(msobject, configobject, actualstate) diff --git a/internal/app/pdns-health-checker/healthchecks/eventcheck/eventcheck.go b/internal/app/pdns-health-checker/healthchecks/eventcheck/eventcheck.go index 33ca69ee..c8379eb9 100644 --- a/internal/app/pdns-health-checker/healthchecks/eventcheck/eventcheck.go +++ b/internal/app/pdns-health-checker/healthchecks/eventcheck/eventcheck.go @@ -3,7 +3,6 @@ package eventcheck import ( "encoding/json" "strconv" - "strings" "time" "github.com/nameserver-systems/pdns-distribute/internal/app/pdns-health-checker/config" @@ -15,8 +14,8 @@ import ( "github.com/nameserver-systems/pdns-distribute/internal/pkg/modelpowerdns" "github.com/nameserver-systems/pdns-distribute/pkg/microservice" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" - "github.com/nameserver-systems/pdns-distribute/pkg/microservice/messaging" - "github.com/nats-io/nats.go/jetstream" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/servicediscovery" + "github.com/nats-io/nats.go" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) @@ -41,35 +40,24 @@ func StartEventCheckHandler(ms *microservice.Microservice, conf *config.ServiceC changeevent := hs.Conf.ChangeEventTopic deleteevent := hs.Conf.DeleteEventTopic - consumer := ms.MessageBroker.GetConsumer() - _, err := consumer.Consume(func(msg jetstream.Msg) { - subject := msg.Subject() - switch { - case strings.HasPrefix(subject, addevent): - go checkAddEvent(msg, hs, waitafterevent) - createreceivedtotal.Inc() - case strings.HasPrefix(subject, changeevent): - go checkChangeEvent(msg, hs, waitafterevent) - changereceivedtotal.Inc() - case strings.HasPrefix(subject, deleteevent): - go checkDeleteEvent(msg, hs, waitafterevent) - deletereceivedtotal.Inc() - default: - logger.DebugLog("[Zone Event Listener]: not matched on topic: " + subject) - } - if err := msg.Ack(); err != nil { - logger.ErrorErrLog(err) - } + ms.MessageBroker.SubscribeAsync(addevent, func(msg *nats.Msg) { + go checkAddEvent(msg, hs, waitafterevent) + createreceivedtotal.Inc() }) - if err != nil { - logger.ErrorErrLog(err) - return - } + ms.MessageBroker.SubscribeAsync(changeevent, func(msg *nats.Msg) { + go checkChangeEvent(msg, hs, waitafterevent) + changereceivedtotal.Inc() + }) + + ms.MessageBroker.SubscribeAsync(deleteevent, func(msg *nats.Msg) { + go checkDeleteEvent(msg, hs, waitafterevent) + deletereceivedtotal.Inc() + }) } -func checkDeleteEvent(msg jetstream.Msg, hs *models.HealthService, waitafterevent time.Duration) { - data := msg.Data() +func checkDeleteEvent(msg *nats.Msg, hs *models.HealthService, waitafterevent time.Duration) { + data := msg.Data deleteEventObject := modelevent.ZoneDeleteEvent{} parseerr := json.Unmarshal(data, &deleteEventObject) @@ -94,8 +82,8 @@ func checkDeleteEvent(msg jetstream.Msg, hs *models.HealthService, waitaftereven checkZoneFreshnessOfSecondaries(eventcheck, hs) } -func checkChangeEvent(msg jetstream.Msg, hs *models.HealthService, waitafterevent time.Duration) { - data := msg.Data() +func checkChangeEvent(msg *nats.Msg, hs *models.HealthService, waitafterevent time.Duration) { + data := msg.Data changeEventObject := modelevent.ZoneChangeEvent{} parseerr := json.Unmarshal(data, &changeEventObject) @@ -120,8 +108,8 @@ func checkChangeEvent(msg jetstream.Msg, hs *models.HealthService, waitaftereven checkZoneFreshnessOfSecondaries(eventcheck, hs) } -func checkAddEvent(msg jetstream.Msg, hs *models.HealthService, waitafterevent time.Duration) { - data := msg.Data() +func checkAddEvent(msg *nats.Msg, hs *models.HealthService, waitafterevent time.Duration) { + data := msg.Data addEventObject := modelevent.ZoneAddEvent{} parseerr := json.Unmarshal(data, &addEventObject) @@ -171,9 +159,8 @@ func getPrimaryZoneSerial(zoneid string, hs *models.HealthService) (int32, error return dnsutils.GetZoneSerialFromFromPrimary(pdnsconnection, zoneid) } -func checkSecondaryZoneFreshness(eventcheck models.EventCheckObject, secondary messaging.ResolvedService, - hs *models.HealthService, -) { +func checkSecondaryZoneFreshness(eventcheck models.EventCheckObject, secondary servicediscovery.ResolvedService, + hs *models.HealthService) { zoneid := eventcheck.Zoneid primaryserial := eventcheck.Primaryserial diff --git a/internal/app/pdns-health-checker/healthchecks/intervallcheck/intervallcheck.go b/internal/app/pdns-health-checker/healthchecks/intervallcheck/intervallcheck.go index 1fa4517e..0f7093b7 100644 --- a/internal/app/pdns-health-checker/healthchecks/intervallcheck/intervallcheck.go +++ b/internal/app/pdns-health-checker/healthchecks/intervallcheck/intervallcheck.go @@ -11,7 +11,7 @@ import ( "github.com/nameserver-systems/pdns-distribute/internal/pkg/modelzone" "github.com/nameserver-systems/pdns-distribute/pkg/microservice" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" - "github.com/nameserver-systems/pdns-distribute/pkg/microservice/messaging" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/servicediscovery" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) @@ -53,9 +53,8 @@ func checkFreshnessOfSecondaries(hs *models.HealthService) { intervalcyclestotal.Inc() } -func checkSecondaryFreshness(secondary messaging.ResolvedService, primaryzonestatemap modelzone.Zonestatemap, - hs *models.HealthService, -) error { +func checkSecondaryFreshness(secondary servicediscovery.ResolvedService, primaryzonestatemap modelzone.Zonestatemap, + hs *models.HealthService) error { secondaryzonestatemap, err := utils.GetSecondaryZoneStateMap(secondary, hs) if err != nil { return err diff --git a/internal/app/pdns-health-checker/healthchecks/intervallsigningsync/intervallsigningsync.go b/internal/app/pdns-health-checker/healthchecks/intervallsigningsync/intervallsigningsync.go index b171b3ac..0ad85195 100644 --- a/internal/app/pdns-health-checker/healthchecks/intervallsigningsync/intervallsigningsync.go +++ b/internal/app/pdns-health-checker/healthchecks/intervallsigningsync/intervallsigningsync.go @@ -13,7 +13,7 @@ import ( "github.com/nameserver-systems/pdns-distribute/internal/pkg/modelzone" "github.com/nameserver-systems/pdns-distribute/pkg/microservice" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" - "github.com/nameserver-systems/pdns-distribute/pkg/microservice/messaging" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/servicediscovery" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) @@ -89,9 +89,8 @@ func refreshSignaturesOnSecondaries(hs *models.HealthService) { signingsynctotal.Inc() } -func refreshSecondarySignatures(secondary messaging.ResolvedService, primaryzonestatemap modelzone.Zonestatemap, - hs *models.HealthService, -) { +func refreshSecondarySignatures(secondary servicediscovery.ResolvedService, primaryzonestatemap modelzone.Zonestatemap, + hs *models.HealthService) { for zoneid := range primaryzonestatemap { eventutils.PublishChangeZoneEvent(hs.Ms, utils.AppendIDToTopic(hs.Conf.ChangeEventTopic, secondary), zoneid) changepublishedtotal.Inc() diff --git a/internal/app/pdns-health-checker/healthchecks/utils/utils.go b/internal/app/pdns-health-checker/healthchecks/utils/utils.go index 3224caa6..f850dc54 100644 --- a/internal/app/pdns-health-checker/healthchecks/utils/utils.go +++ b/internal/app/pdns-health-checker/healthchecks/utils/utils.go @@ -8,16 +8,15 @@ import ( "github.com/nameserver-systems/pdns-distribute/internal/app/pdns-health-checker/models" "github.com/nameserver-systems/pdns-distribute/internal/pkg/modelzone" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" - "github.com/nameserver-systems/pdns-distribute/pkg/microservice/messaging" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/servicediscovery" ) -func AppendIDToTopic(topic string, secondary messaging.ResolvedService) string { +func AppendIDToTopic(topic string, secondary servicediscovery.ResolvedService) string { return topic + "." + secondary.ID } -func GetSecondaryZoneStateMap(secondary messaging.ResolvedService, - hs *models.HealthService, -) (modelzone.Zonestatemap, error) { +func GetSecondaryZoneStateMap(secondary servicediscovery.ResolvedService, + hs *models.HealthService) (modelzone.Zonestatemap, error) { const messagetimeout = 10 * time.Second var transferobject modelzone.Zonestatemaptransferobject @@ -51,9 +50,8 @@ func GetSecondaryZoneStateMap(secondary messaging.ResolvedService, return transferobject.Statemap, nil } -func GetZoneSerialFromSecondary(secondary messaging.ResolvedService, hs *models.HealthService, - zoneid string, -) (int32, error) { +func GetZoneSerialFromSecondary(secondary servicediscovery.ResolvedService, hs *models.HealthService, + zoneid string) (int32, error) { const expectedzonecount = 1 const messagetimeout = 10 * time.Second diff --git a/internal/app/pdns-health-checker/healthorchestrator/healthorchestrator.go b/internal/app/pdns-health-checker/healthorchestrator/healthorchestrator.go index f399e1c1..1c0e57cc 100644 --- a/internal/app/pdns-health-checker/healthorchestrator/healthorchestrator.go +++ b/internal/app/pdns-health-checker/healthorchestrator/healthorchestrator.go @@ -24,33 +24,14 @@ var ( func StartHealthServices(ms *microservice.Microservice) error { serviceconfig := config.GetConfiguration(ms) - - port, err := ms.GetServicePort() - if err != nil { - return err - } - - stream, err := ms.MessageBroker.CreatePersistentMessageStore("pdns-distribute-event-store", []string{"zone.>"}) - if err != nil { - return err - } - - consumer, err := ms.MessageBroker.CreatePersistentMessageReceiver("health-checker-event-client", ms.ID, "add", port, "healthchecker", stream) - if err != nil { - return err - } - - ms.MessageBroker.SetStream(stream) - ms.MessageBroker.SetConsumer(consumer) - actualstate := models.GenerateStateObject() - err = SetActiveZonesInState(serviceconfig, actualstate) - if err != nil { - return err + err2 := SetActiveZonesInState(serviceconfig, actualstate) + if err2 != nil { + return err2 } - err = SetActiveSecondariesInState(ms, actualstate) + err := SetActiveSecondariesInState(ms, actualstate) if err != nil { return err } diff --git a/internal/app/pdns-health-checker/models/modelstate.go b/internal/app/pdns-health-checker/models/modelstate.go index 1fb0e9e5..83f50c3e 100644 --- a/internal/app/pdns-health-checker/models/modelstate.go +++ b/internal/app/pdns-health-checker/models/modelstate.go @@ -5,7 +5,7 @@ import ( "time" "github.com/nameserver-systems/pdns-distribute/internal/pkg/modelzone" - "github.com/nameserver-systems/pdns-distribute/pkg/microservice/messaging" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/servicediscovery" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) @@ -21,7 +21,7 @@ type State struct { zonesChangedAt time.Time secondaryMutex sync.Mutex - activeSecondaries []messaging.ResolvedService + activeSecondaries []servicediscovery.ResolvedService secondariesChangedAt time.Time } @@ -66,7 +66,7 @@ func (s *State) GetExpectedZoneChangeTime() time.Time { return s.zonesChangedAt } -func (s *State) SetActiveSecondaries(secondaries []messaging.ResolvedService) { +func (s *State) SetActiveSecondaries(secondaries []servicediscovery.ResolvedService) { s.secondaryMutex.Lock() secondarystatelockcount.Inc() @@ -79,7 +79,7 @@ func (s *State) SetActiveSecondaries(secondaries []messaging.ResolvedService) { s.secondariesChangedAt = time.Now() } -func (s *State) GetActiveSecondaries() []messaging.ResolvedService { +func (s *State) GetActiveSecondaries() []servicediscovery.ResolvedService { s.secondaryMutex.Lock() secondarystatelockcount.Inc() diff --git a/internal/app/pdns-health-checker/servicediscovery/servicediscovery.go b/internal/app/pdns-health-checker/servicediscovery/servicediscovery.go index 8d4c99be..d26d9267 100644 --- a/internal/app/pdns-health-checker/servicediscovery/servicediscovery.go +++ b/internal/app/pdns-health-checker/servicediscovery/servicediscovery.go @@ -2,7 +2,7 @@ package servicediscovery import ( "github.com/nameserver-systems/pdns-distribute/pkg/microservice" - "github.com/nameserver-systems/pdns-distribute/pkg/microservice/messaging" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/servicediscovery" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) @@ -12,10 +12,8 @@ var ( servicediscoveryerrtotal = promauto.NewCounter(prometheus.CounterOpts{Name: "healthchecker_service_discovery_call_total", ConstLabels: map[string]string{"state": "failed"}, Help: "The total count of service discovery calls"}) ) -func GetActiveSecondaries(ms *microservice.Microservice) ([]messaging.ResolvedService, error) { - stream := ms.MessageBroker.GetStream() - - services, resolveerr := ms.MessageBroker.RetrieveRegisteredConsumers(stream) +func GetActiveSecondaries(ms *microservice.Microservice) ([]servicediscovery.ResolvedService, error) { + services, resolveerr := ms.ServiceDiscovery.GetServices("pdns-secondary-syncer", "") if resolveerr != nil { servicediscoveryerrtotal.Inc() diff --git a/internal/app/pdns-secondary-syncer/eventlistener/eventlistener.go b/internal/app/pdns-secondary-syncer/eventlistener/eventlistener.go index 82aa2fb8..06eaf2f9 100644 --- a/internal/app/pdns-secondary-syncer/eventlistener/eventlistener.go +++ b/internal/app/pdns-secondary-syncer/eventlistener/eventlistener.go @@ -1,8 +1,6 @@ package eventlistener import ( - "strings" - "github.com/nameserver-systems/pdns-distribute/internal/app/pdns-secondary-syncer/config" "github.com/nameserver-systems/pdns-distribute/internal/app/pdns-secondary-syncer/modeljob" "github.com/nameserver-systems/pdns-distribute/internal/app/pdns-secondary-syncer/powerdns" @@ -11,7 +9,6 @@ import ( "github.com/nameserver-systems/pdns-distribute/pkg/microservice" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" "github.com/nats-io/nats.go" - "github.com/nats-io/nats.go/jetstream" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) @@ -26,25 +23,9 @@ var ( func StartEventListenerAndWorker(ms *microservice.Microservice) error { serviceconfig := config.GetConfiguration(ms) - port, err := ms.GetServicePort() - if err != nil { - return err - } - - stream, err := ms.MessageBroker.CreatePersistentMessageStore("pdns-distribute-event-store", []string{"zone.>"}) - if err != nil { - return err - } - - consumer, err := ms.MessageBroker.CreatePersistentMessageReceiver("secondary-syncer-event-client", ms.ID, "add", port, "secondary", stream) - if err != nil { - return err - } - - ms.MessageBroker.SetStream(stream) - ms.MessageBroker.SetConsumer(consumer) - - startZoneEventListeners(ms, serviceconfig) + startAddZoneEventListener(ms, serviceconfig) + startChangeZoneEventListener(ms, serviceconfig) + startDeleteZoneEventListener(ms, serviceconfig) startSecondaryZoneStateEventListener(ms, serviceconfig) primaryzoneprovider.StartAXFRProvider(ms, serviceconfig) @@ -63,51 +44,58 @@ func StopDNSServer() { } } -func startZoneEventListeners(ms *microservice.Microservice, conf *config.ServiceConfiguration) (cancelCtx jetstream.ConsumeContext) { +func startAddZoneEventListener(ms *microservice.Microservice, conf *config.ServiceConfiguration) { addtopic := conf.AddEventTopic + hostaddtopic := addtopic + "." + ms.ID + + addhandler := func(msg *nats.Msg) { + go worker.EnqueJob(&modeljob.PowerDNSAPIJob{ + Jobtype: modeljob.AddZone, + Msg: msg, + Ms: ms, + Conf: conf, + }) + createreceivedtotal.Inc() + } + + ms.MessageBroker.SubscribeAsync(addtopic, addhandler) + ms.MessageBroker.SubscribeAsync(hostaddtopic, addhandler) +} + +func startChangeZoneEventListener(ms *microservice.Microservice, conf *config.ServiceConfiguration) { changetopic := conf.ChangeEventTopic - deltopic := conf.DeleteEventTopic + hostchangetopic := changetopic + "." + ms.ID + + changehandler := func(msg *nats.Msg) { + go worker.EnqueJob(&modeljob.PowerDNSAPIJob{ + Jobtype: modeljob.ChangeZone, + Msg: msg, + Ms: ms, + Conf: conf, + }) + changereceivedtotal.Inc() + } - consumer := ms.MessageBroker.GetConsumer() - cancelCtx, err := consumer.Consume(func(msg jetstream.Msg) { - subject := msg.Subject() - switch { - case strings.HasPrefix(subject, addtopic): - go worker.EnqueJob(&modeljob.PowerDNSAPIJob{ - Jobtype: modeljob.AddZone, - Msg: msg, - Ms: ms, - Conf: conf, - }) - createreceivedtotal.Inc() - case strings.HasPrefix(subject, changetopic): - go worker.EnqueJob(&modeljob.PowerDNSAPIJob{ - Jobtype: modeljob.ChangeZone, - Msg: msg, - Ms: ms, - Conf: conf, - }) - changereceivedtotal.Inc() - case strings.HasPrefix(subject, deltopic): - go worker.EnqueJob(&modeljob.PowerDNSAPIJob{ - Jobtype: modeljob.DeleteZone, - Msg: msg, - Ms: ms, - Conf: conf, - }) - deletereceivedtotal.Inc() - default: - logger.DebugLog("[Zone Event Listener]: not matched on topic: " + subject) - } - if err := msg.Ack(); err != nil { - logger.ErrorErrLog(err) - } - }) - if err != nil { - logger.ErrorErrLog(err) + ms.MessageBroker.SubscribeAsync(changetopic, changehandler) + ms.MessageBroker.SubscribeAsync(hostchangetopic, changehandler) +} + +func startDeleteZoneEventListener(ms *microservice.Microservice, conf *config.ServiceConfiguration) { + deltopic := conf.DeleteEventTopic + hostdeltopic := deltopic + "." + ms.ID + + delhandler := func(msg *nats.Msg) { + go worker.EnqueJob(&modeljob.PowerDNSAPIJob{ + Jobtype: modeljob.DeleteZone, + Msg: msg, + Ms: ms, + Conf: conf, + }) + deletereceivedtotal.Inc() } - return + ms.MessageBroker.SubscribeAsync(deltopic, delhandler) + ms.MessageBroker.SubscribeAsync(hostdeltopic, delhandler) } func startSecondaryZoneStateEventListener(ms *microservice.Microservice, conf *config.ServiceConfiguration) { @@ -119,7 +107,5 @@ func startSecondaryZoneStateEventListener(ms *microservice.Microservice, conf *c zonestaterequesttotal.Inc() } - if err := ms.MessageBroker.SubscribeAsync(receivertopic, zonestatehandler); err != nil { - logger.FatalErrLog(err) - } + ms.MessageBroker.SubscribeAsync(receivertopic, zonestatehandler) } diff --git a/internal/app/pdns-secondary-syncer/modeljob/modeljob.go b/internal/app/pdns-secondary-syncer/modeljob/modeljob.go index 89f07899..fe43f61a 100644 --- a/internal/app/pdns-secondary-syncer/modeljob/modeljob.go +++ b/internal/app/pdns-secondary-syncer/modeljob/modeljob.go @@ -3,7 +3,7 @@ package modeljob import ( "github.com/nameserver-systems/pdns-distribute/internal/app/pdns-secondary-syncer/config" "github.com/nameserver-systems/pdns-distribute/pkg/microservice" - "github.com/nats-io/nats.go/jetstream" + "github.com/nats-io/nats.go" ) const ( @@ -14,7 +14,7 @@ const ( type PowerDNSAPIJob struct { Jobtype int - Msg jetstream.Msg + Msg *nats.Msg Ms *microservice.Microservice Conf *config.ServiceConfiguration } diff --git a/internal/app/pdns-secondary-syncer/powerdns/powerdns.go b/internal/app/pdns-secondary-syncer/powerdns/powerdns.go index 729c17c2..42300a47 100644 --- a/internal/app/pdns-secondary-syncer/powerdns/powerdns.go +++ b/internal/app/pdns-secondary-syncer/powerdns/powerdns.go @@ -13,7 +13,6 @@ import ( "github.com/nameserver-systems/pdns-distribute/pkg/microservice" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" "github.com/nats-io/nats.go" - "github.com/nats-io/nats.go/jetstream" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" ) @@ -40,7 +39,7 @@ var ( workerlockcount = promauto.NewGauge(prometheus.GaugeOpts{Name: "secondarysyncer_worker_lock_count", Help: "The actual count of worker locks"}) ) -func AddZone(msg jetstream.Msg, conf *config.ServiceConfiguration) { +func AddZone(msg *nats.Msg, conf *config.ServiceConfiguration) { pdnsconnection := modelpowerdns.PDNSconnectionobject{ PowerDNSurl: conf.PowerDNSURL, ServerID: conf.PowerDNSServerID, @@ -144,7 +143,7 @@ func CreateZonePerAPI(zoneid string, conf *config.ServiceConfiguration) error { Apitoken: conf.PowerDNSAPIToken, } - payload, preparationerr := prepareCreateZoneRequest(zoneid, conf.AXFRPrimaryAddress) + payload, preparationerr := prepareCreateZoneRequest(zoneid) if preparationerr != nil { return preparationerr } @@ -164,14 +163,14 @@ func CreateZonePerAPI(zoneid string, conf *config.ServiceConfiguration) error { return nil } -func prepareCreateZoneRequest(zoneid, axfrPrimaryAddress string) ([]byte, error) { +func prepareCreateZoneRequest(zoneid string) ([]byte, error) { zonecreation := modelpowerdns.Zone{ ID: zoneid, Name: zoneid, Kind: "Slave", - Masters: []string{axfrPrimaryAddress}, + Masters: []string{"127.0.0.1:20102"}, Nameservers: make([]string, 0), - // Zone: zonedata.ZoneData, // DISABLED DUE TO AXFR ZONES + // Zone: zonedata.ZoneData, // DISABLED DUE TO SLAVING ZONES SoaEdit: "NONE", SoaEditAPI: "OFF", Presigned: true, @@ -237,8 +236,8 @@ func waitForPrimaryToStoreZoneAfterChange(conf *config.ServiceConfiguration) { time.Sleep(conf.EventDelay) } -func getZoneIDFromAddEventMessage(msg jetstream.Msg) (string, error) { - incomingmdata := msg.Data() +func getZoneIDFromAddEventMessage(msg *nats.Msg) (string, error) { + incomingmdata := msg.Data addevent := modelevent.ZoneAddEvent{} unmarshalerr := json.Unmarshal(incomingmdata, &addevent) @@ -251,8 +250,8 @@ func getZoneIDFromAddEventMessage(msg jetstream.Msg) (string, error) { return addevent.Zone, nil } -func getZoneIDFromChangeEventMessage(msg jetstream.Msg) (string, error) { - incomingmdata := msg.Data() +func getZoneIDFromChangeEventMessage(msg *nats.Msg) (string, error) { + incomingmdata := msg.Data changeevent := modelevent.ZoneChangeEvent{} unmarshalerr := json.Unmarshal(incomingmdata, &changeevent) @@ -265,8 +264,8 @@ func getZoneIDFromChangeEventMessage(msg jetstream.Msg) (string, error) { return changeevent.Zone, nil } -func getZoneIDFromDeleteEventMessage(msg jetstream.Msg) (string, error) { - incomingmdata := msg.Data() +func getZoneIDFromDeleteEventMessage(msg *nats.Msg) (string, error) { + incomingmdata := msg.Data deleteevent := modelevent.ZoneDeleteEvent{} unmarshalerr := json.Unmarshal(incomingmdata, &deleteevent) @@ -279,7 +278,7 @@ func getZoneIDFromDeleteEventMessage(msg jetstream.Msg) (string, error) { return deleteevent.Zone, nil } -func ChangeZone(msg jetstream.Msg, conf *config.ServiceConfiguration) { //nolint:funlen +func ChangeZone(msg *nats.Msg, conf *config.ServiceConfiguration) { //nolint:funlen pdnsconnection := modelpowerdns.PDNSconnectionobject{ PowerDNSurl: conf.PowerDNSURL, ServerID: conf.PowerDNSServerID, @@ -350,7 +349,7 @@ func ChangeZone(msg jetstream.Msg, conf *config.ServiceConfiguration) { //nolint logger.DebugLog("[Change Zone] triggered for zone: " + zoneid + " with: AXFR") // zonedata.ZoneData) } -func DeleteZone(msg jetstream.Msg, conf *config.ServiceConfiguration) { +func DeleteZone(msg *nats.Msg, conf *config.ServiceConfiguration) { pdnsconnection := modelpowerdns.PDNSconnectionobject{ PowerDNSurl: conf.PowerDNSURL, ServerID: conf.PowerDNSServerID, diff --git a/internal/app/pdns-secondary-syncer/primaryzoneprovider/primary.go b/internal/app/pdns-secondary-syncer/primaryzoneprovider/primary.go index 6e1dc342..39963dc1 100644 --- a/internal/app/pdns-secondary-syncer/primaryzoneprovider/primary.go +++ b/internal/app/pdns-secondary-syncer/primaryzoneprovider/primary.go @@ -125,9 +125,7 @@ func handleAXFR(writer dns.ResponseWriter, msg *dns.Msg, conf *config.ServiceCon ch <- &dns.Envelope{RR: ansrrset} close(ch) wg.Wait() - if err := writer.Close(); err != nil { - logger.ErrorErrLog(err) - } + writer.Close() } func getZoneID(msg *dns.Msg) string { diff --git a/internal/app/pdns-secondary-syncer/worker/worker.go b/internal/app/pdns-secondary-syncer/worker/worker.go index f40c256c..14e410c0 100644 --- a/internal/app/pdns-secondary-syncer/worker/worker.go +++ b/internal/app/pdns-secondary-syncer/worker/worker.go @@ -26,7 +26,7 @@ func EnqueJob(j *modeljob.PowerDNSAPIJob) { Workerqueue <- j logger.DebugLog("[Enqueue Job] Job successfully enqueued. Jobs in workerqueue: " + strconv.Itoa(len(Workerqueue))) logger.DebugLog("[Enqueue Job] Go Routine Count: " + strconv.Itoa(runtime.NumGoroutine())) - logger.DebugLog("[Enqueue Job] New Job: " + string(j.Msg.Data())) + logger.DebugLog("[Enqueue Job] New Job: " + string(j.Msg.Data)) } func CloseWorkerQueue() { diff --git a/internal/app/pdns-zone-provider/messaging/messaging.go b/internal/app/pdns-zone-provider/messaging/messaging.go index e33708c2..0516710b 100644 --- a/internal/app/pdns-zone-provider/messaging/messaging.go +++ b/internal/app/pdns-zone-provider/messaging/messaging.go @@ -4,7 +4,6 @@ import ( "github.com/nameserver-systems/pdns-distribute/internal/app/pdns-zone-provider/config" "github.com/nameserver-systems/pdns-distribute/internal/app/pdns-zone-provider/powerdns" "github.com/nameserver-systems/pdns-distribute/pkg/microservice" - "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" "github.com/nats-io/nats.go" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" @@ -16,11 +15,8 @@ func SubscribeToIncomingMessages(ms *microservice.Microservice, serviceconfig *c topic := serviceconfig.ReceiverTopic queue := "worker" - err := ms.MessageBroker.SubscribeQueueAsync(topic, queue, func(msg *nats.Msg) { + ms.MessageBroker.SubscribeQueueAsync(topic, queue, func(msg *nats.Msg) { go powerdns.ProcessRequest(msg, serviceconfig) requesttotal.Inc() }) - if err != nil { - logger.FatalErrLog(err) - } } diff --git a/internal/pkg/eventutils/eventutils.go b/internal/pkg/eventutils/eventutils.go index 855f4e62..0b5e73ec 100644 --- a/internal/pkg/eventutils/eventutils.go +++ b/internal/pkg/eventutils/eventutils.go @@ -20,9 +20,7 @@ func PublishDeleteZoneEvent(ms *microservice.Microservice, topic string, zoneid logger.ErrorErrLog(marshalerr) } - if err := ms.MessageBroker.PersistedPublish(topic, payload); err != nil { - logger.ErrorErrLog(err) - } + ms.MessageBroker.Publish(topic, payload) logger.DebugLog("[Delete Zone Event] triggered for zone: " + zoneid + " on topic: " + topic) //nolint:goconst } @@ -37,9 +35,7 @@ func PublishChangeZoneEvent(ms *microservice.Microservice, topic string, zoneid logger.ErrorErrLog(marshalerr) } - if err := ms.MessageBroker.PersistedPublish(topic, payload); err != nil { - logger.ErrorErrLog(err) - } + ms.MessageBroker.Publish(topic, payload) logger.DebugLog("[Change Zone Event] triggered for zone: " + zoneid + " on topic: " + topic) } @@ -54,8 +50,6 @@ func PublishCreateZoneEvent(ms *microservice.Microservice, topic string, zoneid logger.ErrorErrLog(marshalerr) } - if err := ms.MessageBroker.PersistedPublish(topic, payload); err != nil { - logger.ErrorErrLog(err) - } + ms.MessageBroker.Publish(topic, payload) logger.DebugLog("[Create Zone Event] triggered for zone: " + zoneid + " on topic: " + topic) } diff --git a/internal/pkg/httputils/httputils_test.go b/internal/pkg/httputils/httputils_test.go index 11611b73..4f014e24 100644 --- a/internal/pkg/httputils/httputils_test.go +++ b/internal/pkg/httputils/httputils_test.go @@ -128,7 +128,7 @@ func TestGetZoneIDFromRequest(t *testing.T) { //nolint:funlen mux := http.NewServeMux() mux.HandleFunc("GET /{zone_id}", func(writer http.ResponseWriter, request *http.Request) { actualZone, err := GetZoneIDFromRequest(request) - require.NoError(t, err) + assert.NoError(t, err) _, _ = fmt.Fprint(writer, actualZone) }) @@ -150,7 +150,7 @@ func TestGetZoneIDFromRequest(t *testing.T) { //nolint:funlen mux := http.NewServeMux() mux.HandleFunc("POST /", func(writer http.ResponseWriter, request *http.Request) { actualZone, err := GetZoneIDFromRequest(request) - require.NoError(t, err) + assert.NoError(t, err) _, _ = fmt.Fprint(writer, actualZone) }) @@ -174,7 +174,7 @@ func TestGetZoneIDFromRequest(t *testing.T) { //nolint:funlen mux := http.NewServeMux() mux.HandleFunc("POST /", func(writer http.ResponseWriter, request *http.Request) { actualZone, err := GetZoneIDFromRequest(request) - require.EqualError(t, err, errZoneIDNotFound.Error()) + assert.EqualError(t, err, errZoneIDNotFound.Error()) _, _ = fmt.Fprint(writer, actualZone) }) @@ -246,10 +246,10 @@ func Test_getZoneIDFromRequestBody(t *testing.T) { func TestExecutePowerDNSRequest(t *testing.T) { t.Run("success", func(t *testing.T) { s := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) { - require.Equal(t, "1234", request.Header.Get("X-API-Key")) + assert.Equal(t, "1234", request.Header.Get("X-API-Key")) data, err := io.ReadAll(request.Body) - require.NoError(t, err) - require.Equal(t, "{}", string(data)) + assert.NoError(t, err) + assert.Equal(t, "{}", string(data)) _, _ = fmt.Fprint(writer, "ok") })) diff --git a/internal/pkg/mocks/jetstream.go b/internal/pkg/mocks/jetstream.go deleted file mode 100644 index b113aceb..00000000 --- a/internal/pkg/mocks/jetstream.go +++ /dev/null @@ -1,585 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/nats-io/nats.go/jetstream (interfaces: JetStream) -// -// Generated by this command: -// -// mockgen --destination ../../../internal/pkg/mocks/jetstream.go --package mocks github.com/nats-io/nats.go/jetstream JetStream -// - -// Package mocks is a generated GoMock package. -package mocks - -import ( - context "context" - reflect "reflect" - - nats "github.com/nats-io/nats.go" - jetstream "github.com/nats-io/nats.go/jetstream" - gomock "go.uber.org/mock/gomock" -) - -// MockJetStream is a mock of JetStream interface. -type MockJetStream struct { - ctrl *gomock.Controller - recorder *MockJetStreamMockRecorder -} - -// MockJetStreamMockRecorder is the mock recorder for MockJetStream. -type MockJetStreamMockRecorder struct { - mock *MockJetStream -} - -// NewMockJetStream creates a new mock instance. -func NewMockJetStream(ctrl *gomock.Controller) *MockJetStream { - mock := &MockJetStream{ctrl: ctrl} - mock.recorder = &MockJetStreamMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockJetStream) EXPECT() *MockJetStreamMockRecorder { - return m.recorder -} - -// AccountInfo mocks base method. -func (m *MockJetStream) AccountInfo(arg0 context.Context) (*jetstream.AccountInfo, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "AccountInfo", arg0) - ret0, _ := ret[0].(*jetstream.AccountInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// AccountInfo indicates an expected call of AccountInfo. -func (mr *MockJetStreamMockRecorder) AccountInfo(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AccountInfo", reflect.TypeOf((*MockJetStream)(nil).AccountInfo), arg0) -} - -// Consumer mocks base method. -func (m *MockJetStream) Consumer(arg0 context.Context, arg1, arg2 string) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Consumer", arg0, arg1, arg2) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Consumer indicates an expected call of Consumer. -func (mr *MockJetStreamMockRecorder) Consumer(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Consumer", reflect.TypeOf((*MockJetStream)(nil).Consumer), arg0, arg1, arg2) -} - -// CreateConsumer mocks base method. -func (m *MockJetStream) CreateConsumer(arg0 context.Context, arg1 string, arg2 jetstream.ConsumerConfig) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateConsumer", arg0, arg1, arg2) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateConsumer indicates an expected call of CreateConsumer. -func (mr *MockJetStreamMockRecorder) CreateConsumer(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateConsumer", reflect.TypeOf((*MockJetStream)(nil).CreateConsumer), arg0, arg1, arg2) -} - -// CreateKeyValue mocks base method. -func (m *MockJetStream) CreateKeyValue(arg0 context.Context, arg1 jetstream.KeyValueConfig) (jetstream.KeyValue, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateKeyValue", arg0, arg1) - ret0, _ := ret[0].(jetstream.KeyValue) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateKeyValue indicates an expected call of CreateKeyValue. -func (mr *MockJetStreamMockRecorder) CreateKeyValue(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateKeyValue", reflect.TypeOf((*MockJetStream)(nil).CreateKeyValue), arg0, arg1) -} - -// CreateObjectStore mocks base method. -func (m *MockJetStream) CreateObjectStore(arg0 context.Context, arg1 jetstream.ObjectStoreConfig) (jetstream.ObjectStore, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateObjectStore", arg0, arg1) - ret0, _ := ret[0].(jetstream.ObjectStore) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateObjectStore indicates an expected call of CreateObjectStore. -func (mr *MockJetStreamMockRecorder) CreateObjectStore(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateObjectStore", reflect.TypeOf((*MockJetStream)(nil).CreateObjectStore), arg0, arg1) -} - -// CreateOrUpdateConsumer mocks base method. -func (m *MockJetStream) CreateOrUpdateConsumer(arg0 context.Context, arg1 string, arg2 jetstream.ConsumerConfig) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateConsumer", arg0, arg1, arg2) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateOrUpdateConsumer indicates an expected call of CreateOrUpdateConsumer. -func (mr *MockJetStreamMockRecorder) CreateOrUpdateConsumer(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateConsumer", reflect.TypeOf((*MockJetStream)(nil).CreateOrUpdateConsumer), arg0, arg1, arg2) -} - -// CreateOrUpdateKeyValue mocks base method. -func (m *MockJetStream) CreateOrUpdateKeyValue(arg0 context.Context, arg1 jetstream.KeyValueConfig) (jetstream.KeyValue, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateKeyValue", arg0, arg1) - ret0, _ := ret[0].(jetstream.KeyValue) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateOrUpdateKeyValue indicates an expected call of CreateOrUpdateKeyValue. -func (mr *MockJetStreamMockRecorder) CreateOrUpdateKeyValue(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateKeyValue", reflect.TypeOf((*MockJetStream)(nil).CreateOrUpdateKeyValue), arg0, arg1) -} - -// CreateOrUpdateObjectStore mocks base method. -func (m *MockJetStream) CreateOrUpdateObjectStore(arg0 context.Context, arg1 jetstream.ObjectStoreConfig) (jetstream.ObjectStore, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateObjectStore", arg0, arg1) - ret0, _ := ret[0].(jetstream.ObjectStore) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateOrUpdateObjectStore indicates an expected call of CreateOrUpdateObjectStore. -func (mr *MockJetStreamMockRecorder) CreateOrUpdateObjectStore(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateObjectStore", reflect.TypeOf((*MockJetStream)(nil).CreateOrUpdateObjectStore), arg0, arg1) -} - -// CreateOrUpdateStream mocks base method. -func (m *MockJetStream) CreateOrUpdateStream(arg0 context.Context, arg1 jetstream.StreamConfig) (jetstream.Stream, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateStream", arg0, arg1) - ret0, _ := ret[0].(jetstream.Stream) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateOrUpdateStream indicates an expected call of CreateOrUpdateStream. -func (mr *MockJetStreamMockRecorder) CreateOrUpdateStream(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateStream", reflect.TypeOf((*MockJetStream)(nil).CreateOrUpdateStream), arg0, arg1) -} - -// CreateStream mocks base method. -func (m *MockJetStream) CreateStream(arg0 context.Context, arg1 jetstream.StreamConfig) (jetstream.Stream, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateStream", arg0, arg1) - ret0, _ := ret[0].(jetstream.Stream) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateStream indicates an expected call of CreateStream. -func (mr *MockJetStreamMockRecorder) CreateStream(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateStream", reflect.TypeOf((*MockJetStream)(nil).CreateStream), arg0, arg1) -} - -// DeleteConsumer mocks base method. -func (m *MockJetStream) DeleteConsumer(arg0 context.Context, arg1, arg2 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteConsumer", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteConsumer indicates an expected call of DeleteConsumer. -func (mr *MockJetStreamMockRecorder) DeleteConsumer(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConsumer", reflect.TypeOf((*MockJetStream)(nil).DeleteConsumer), arg0, arg1, arg2) -} - -// DeleteKeyValue mocks base method. -func (m *MockJetStream) DeleteKeyValue(arg0 context.Context, arg1 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteKeyValue", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteKeyValue indicates an expected call of DeleteKeyValue. -func (mr *MockJetStreamMockRecorder) DeleteKeyValue(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteKeyValue", reflect.TypeOf((*MockJetStream)(nil).DeleteKeyValue), arg0, arg1) -} - -// DeleteObjectStore mocks base method. -func (m *MockJetStream) DeleteObjectStore(arg0 context.Context, arg1 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteObjectStore", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteObjectStore indicates an expected call of DeleteObjectStore. -func (mr *MockJetStreamMockRecorder) DeleteObjectStore(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteObjectStore", reflect.TypeOf((*MockJetStream)(nil).DeleteObjectStore), arg0, arg1) -} - -// DeleteStream mocks base method. -func (m *MockJetStream) DeleteStream(arg0 context.Context, arg1 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteStream", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteStream indicates an expected call of DeleteStream. -func (mr *MockJetStreamMockRecorder) DeleteStream(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteStream", reflect.TypeOf((*MockJetStream)(nil).DeleteStream), arg0, arg1) -} - -// KeyValue mocks base method. -func (m *MockJetStream) KeyValue(arg0 context.Context, arg1 string) (jetstream.KeyValue, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "KeyValue", arg0, arg1) - ret0, _ := ret[0].(jetstream.KeyValue) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// KeyValue indicates an expected call of KeyValue. -func (mr *MockJetStreamMockRecorder) KeyValue(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeyValue", reflect.TypeOf((*MockJetStream)(nil).KeyValue), arg0, arg1) -} - -// KeyValueStoreNames mocks base method. -func (m *MockJetStream) KeyValueStoreNames(arg0 context.Context) jetstream.KeyValueNamesLister { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "KeyValueStoreNames", arg0) - ret0, _ := ret[0].(jetstream.KeyValueNamesLister) - return ret0 -} - -// KeyValueStoreNames indicates an expected call of KeyValueStoreNames. -func (mr *MockJetStreamMockRecorder) KeyValueStoreNames(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeyValueStoreNames", reflect.TypeOf((*MockJetStream)(nil).KeyValueStoreNames), arg0) -} - -// KeyValueStores mocks base method. -func (m *MockJetStream) KeyValueStores(arg0 context.Context) jetstream.KeyValueLister { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "KeyValueStores", arg0) - ret0, _ := ret[0].(jetstream.KeyValueLister) - return ret0 -} - -// KeyValueStores indicates an expected call of KeyValueStores. -func (mr *MockJetStreamMockRecorder) KeyValueStores(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "KeyValueStores", reflect.TypeOf((*MockJetStream)(nil).KeyValueStores), arg0) -} - -// ListStreams mocks base method. -func (m *MockJetStream) ListStreams(arg0 context.Context, arg1 ...jetstream.StreamListOpt) jetstream.StreamInfoLister { - m.ctrl.T.Helper() - varargs := []any{arg0} - for _, a := range arg1 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "ListStreams", varargs...) - ret0, _ := ret[0].(jetstream.StreamInfoLister) - return ret0 -} - -// ListStreams indicates an expected call of ListStreams. -func (mr *MockJetStreamMockRecorder) ListStreams(arg0 any, arg1 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0}, arg1...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListStreams", reflect.TypeOf((*MockJetStream)(nil).ListStreams), varargs...) -} - -// ObjectStore mocks base method. -func (m *MockJetStream) ObjectStore(arg0 context.Context, arg1 string) (jetstream.ObjectStore, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ObjectStore", arg0, arg1) - ret0, _ := ret[0].(jetstream.ObjectStore) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// ObjectStore indicates an expected call of ObjectStore. -func (mr *MockJetStreamMockRecorder) ObjectStore(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ObjectStore", reflect.TypeOf((*MockJetStream)(nil).ObjectStore), arg0, arg1) -} - -// ObjectStoreNames mocks base method. -func (m *MockJetStream) ObjectStoreNames(arg0 context.Context) jetstream.ObjectStoreNamesLister { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ObjectStoreNames", arg0) - ret0, _ := ret[0].(jetstream.ObjectStoreNamesLister) - return ret0 -} - -// ObjectStoreNames indicates an expected call of ObjectStoreNames. -func (mr *MockJetStreamMockRecorder) ObjectStoreNames(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ObjectStoreNames", reflect.TypeOf((*MockJetStream)(nil).ObjectStoreNames), arg0) -} - -// ObjectStores mocks base method. -func (m *MockJetStream) ObjectStores(arg0 context.Context) jetstream.ObjectStoresLister { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ObjectStores", arg0) - ret0, _ := ret[0].(jetstream.ObjectStoresLister) - return ret0 -} - -// ObjectStores indicates an expected call of ObjectStores. -func (mr *MockJetStreamMockRecorder) ObjectStores(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ObjectStores", reflect.TypeOf((*MockJetStream)(nil).ObjectStores), arg0) -} - -// OrderedConsumer mocks base method. -func (m *MockJetStream) OrderedConsumer(arg0 context.Context, arg1 string, arg2 jetstream.OrderedConsumerConfig) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "OrderedConsumer", arg0, arg1, arg2) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// OrderedConsumer indicates an expected call of OrderedConsumer. -func (mr *MockJetStreamMockRecorder) OrderedConsumer(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrderedConsumer", reflect.TypeOf((*MockJetStream)(nil).OrderedConsumer), arg0, arg1, arg2) -} - -// Publish mocks base method. -func (m *MockJetStream) Publish(arg0 context.Context, arg1 string, arg2 []byte, arg3 ...jetstream.PublishOpt) (*jetstream.PubAck, error) { - m.ctrl.T.Helper() - varargs := []any{arg0, arg1, arg2} - for _, a := range arg3 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Publish", varargs...) - ret0, _ := ret[0].(*jetstream.PubAck) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Publish indicates an expected call of Publish. -func (mr *MockJetStreamMockRecorder) Publish(arg0, arg1, arg2 any, arg3 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0, arg1, arg2}, arg3...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Publish", reflect.TypeOf((*MockJetStream)(nil).Publish), varargs...) -} - -// PublishAsync mocks base method. -func (m *MockJetStream) PublishAsync(arg0 string, arg1 []byte, arg2 ...jetstream.PublishOpt) (jetstream.PubAckFuture, error) { - m.ctrl.T.Helper() - varargs := []any{arg0, arg1} - for _, a := range arg2 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "PublishAsync", varargs...) - ret0, _ := ret[0].(jetstream.PubAckFuture) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// PublishAsync indicates an expected call of PublishAsync. -func (mr *MockJetStreamMockRecorder) PublishAsync(arg0, arg1 any, arg2 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0, arg1}, arg2...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishAsync", reflect.TypeOf((*MockJetStream)(nil).PublishAsync), varargs...) -} - -// PublishAsyncComplete mocks base method. -func (m *MockJetStream) PublishAsyncComplete() <-chan struct{} { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PublishAsyncComplete") - ret0, _ := ret[0].(<-chan struct{}) - return ret0 -} - -// PublishAsyncComplete indicates an expected call of PublishAsyncComplete. -func (mr *MockJetStreamMockRecorder) PublishAsyncComplete() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishAsyncComplete", reflect.TypeOf((*MockJetStream)(nil).PublishAsyncComplete)) -} - -// PublishAsyncPending mocks base method. -func (m *MockJetStream) PublishAsyncPending() int { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "PublishAsyncPending") - ret0, _ := ret[0].(int) - return ret0 -} - -// PublishAsyncPending indicates an expected call of PublishAsyncPending. -func (mr *MockJetStreamMockRecorder) PublishAsyncPending() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishAsyncPending", reflect.TypeOf((*MockJetStream)(nil).PublishAsyncPending)) -} - -// PublishMsg mocks base method. -func (m *MockJetStream) PublishMsg(arg0 context.Context, arg1 *nats.Msg, arg2 ...jetstream.PublishOpt) (*jetstream.PubAck, error) { - m.ctrl.T.Helper() - varargs := []any{arg0, arg1} - for _, a := range arg2 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "PublishMsg", varargs...) - ret0, _ := ret[0].(*jetstream.PubAck) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// PublishMsg indicates an expected call of PublishMsg. -func (mr *MockJetStreamMockRecorder) PublishMsg(arg0, arg1 any, arg2 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0, arg1}, arg2...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishMsg", reflect.TypeOf((*MockJetStream)(nil).PublishMsg), varargs...) -} - -// PublishMsgAsync mocks base method. -func (m *MockJetStream) PublishMsgAsync(arg0 *nats.Msg, arg1 ...jetstream.PublishOpt) (jetstream.PubAckFuture, error) { - m.ctrl.T.Helper() - varargs := []any{arg0} - for _, a := range arg1 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "PublishMsgAsync", varargs...) - ret0, _ := ret[0].(jetstream.PubAckFuture) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// PublishMsgAsync indicates an expected call of PublishMsgAsync. -func (mr *MockJetStreamMockRecorder) PublishMsgAsync(arg0 any, arg1 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0}, arg1...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PublishMsgAsync", reflect.TypeOf((*MockJetStream)(nil).PublishMsgAsync), varargs...) -} - -// Stream mocks base method. -func (m *MockJetStream) Stream(arg0 context.Context, arg1 string) (jetstream.Stream, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Stream", arg0, arg1) - ret0, _ := ret[0].(jetstream.Stream) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Stream indicates an expected call of Stream. -func (mr *MockJetStreamMockRecorder) Stream(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stream", reflect.TypeOf((*MockJetStream)(nil).Stream), arg0, arg1) -} - -// StreamNameBySubject mocks base method. -func (m *MockJetStream) StreamNameBySubject(arg0 context.Context, arg1 string) (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "StreamNameBySubject", arg0, arg1) - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// StreamNameBySubject indicates an expected call of StreamNameBySubject. -func (mr *MockJetStreamMockRecorder) StreamNameBySubject(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StreamNameBySubject", reflect.TypeOf((*MockJetStream)(nil).StreamNameBySubject), arg0, arg1) -} - -// StreamNames mocks base method. -func (m *MockJetStream) StreamNames(arg0 context.Context, arg1 ...jetstream.StreamListOpt) jetstream.StreamNameLister { - m.ctrl.T.Helper() - varargs := []any{arg0} - for _, a := range arg1 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "StreamNames", varargs...) - ret0, _ := ret[0].(jetstream.StreamNameLister) - return ret0 -} - -// StreamNames indicates an expected call of StreamNames. -func (mr *MockJetStreamMockRecorder) StreamNames(arg0 any, arg1 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0}, arg1...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StreamNames", reflect.TypeOf((*MockJetStream)(nil).StreamNames), varargs...) -} - -// UpdateConsumer mocks base method. -func (m *MockJetStream) UpdateConsumer(arg0 context.Context, arg1 string, arg2 jetstream.ConsumerConfig) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateConsumer", arg0, arg1, arg2) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateConsumer indicates an expected call of UpdateConsumer. -func (mr *MockJetStreamMockRecorder) UpdateConsumer(arg0, arg1, arg2 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConsumer", reflect.TypeOf((*MockJetStream)(nil).UpdateConsumer), arg0, arg1, arg2) -} - -// UpdateKeyValue mocks base method. -func (m *MockJetStream) UpdateKeyValue(arg0 context.Context, arg1 jetstream.KeyValueConfig) (jetstream.KeyValue, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateKeyValue", arg0, arg1) - ret0, _ := ret[0].(jetstream.KeyValue) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateKeyValue indicates an expected call of UpdateKeyValue. -func (mr *MockJetStreamMockRecorder) UpdateKeyValue(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateKeyValue", reflect.TypeOf((*MockJetStream)(nil).UpdateKeyValue), arg0, arg1) -} - -// UpdateObjectStore mocks base method. -func (m *MockJetStream) UpdateObjectStore(arg0 context.Context, arg1 jetstream.ObjectStoreConfig) (jetstream.ObjectStore, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateObjectStore", arg0, arg1) - ret0, _ := ret[0].(jetstream.ObjectStore) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateObjectStore indicates an expected call of UpdateObjectStore. -func (mr *MockJetStreamMockRecorder) UpdateObjectStore(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateObjectStore", reflect.TypeOf((*MockJetStream)(nil).UpdateObjectStore), arg0, arg1) -} - -// UpdateStream mocks base method. -func (m *MockJetStream) UpdateStream(arg0 context.Context, arg1 jetstream.StreamConfig) (jetstream.Stream, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateStream", arg0, arg1) - ret0, _ := ret[0].(jetstream.Stream) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateStream indicates an expected call of UpdateStream. -func (mr *MockJetStreamMockRecorder) UpdateStream(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStream", reflect.TypeOf((*MockJetStream)(nil).UpdateStream), arg0, arg1) -} diff --git a/internal/pkg/mocks/jetstream_consumer_info_listener.go b/internal/pkg/mocks/jetstream_consumer_info_listener.go deleted file mode 100644 index 4149f5c5..00000000 --- a/internal/pkg/mocks/jetstream_consumer_info_listener.go +++ /dev/null @@ -1,68 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/nats-io/nats.go/jetstream (interfaces: ConsumerInfoLister) -// -// Generated by this command: -// -// mockgen --destination ../../../internal/pkg/mocks/jetstream_consumer_info_listener.go --package mocks github.com/nats-io/nats.go/jetstream ConsumerInfoLister -// - -// Package mocks is a generated GoMock package. -package mocks - -import ( - reflect "reflect" - - jetstream "github.com/nats-io/nats.go/jetstream" - gomock "go.uber.org/mock/gomock" -) - -// MockConsumerInfoLister is a mock of ConsumerInfoLister interface. -type MockConsumerInfoLister struct { - ctrl *gomock.Controller - recorder *MockConsumerInfoListerMockRecorder -} - -// MockConsumerInfoListerMockRecorder is the mock recorder for MockConsumerInfoLister. -type MockConsumerInfoListerMockRecorder struct { - mock *MockConsumerInfoLister -} - -// NewMockConsumerInfoLister creates a new mock instance. -func NewMockConsumerInfoLister(ctrl *gomock.Controller) *MockConsumerInfoLister { - mock := &MockConsumerInfoLister{ctrl: ctrl} - mock.recorder = &MockConsumerInfoListerMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockConsumerInfoLister) EXPECT() *MockConsumerInfoListerMockRecorder { - return m.recorder -} - -// Err mocks base method. -func (m *MockConsumerInfoLister) Err() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Err") - ret0, _ := ret[0].(error) - return ret0 -} - -// Err indicates an expected call of Err. -func (mr *MockConsumerInfoListerMockRecorder) Err() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Err", reflect.TypeOf((*MockConsumerInfoLister)(nil).Err)) -} - -// Info mocks base method. -func (m *MockConsumerInfoLister) Info() <-chan *jetstream.ConsumerInfo { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Info") - ret0, _ := ret[0].(<-chan *jetstream.ConsumerInfo) - return ret0 -} - -// Info indicates an expected call of Info. -func (mr *MockConsumerInfoListerMockRecorder) Info() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockConsumerInfoLister)(nil).Info)) -} diff --git a/internal/pkg/mocks/jetstream_stream.go b/internal/pkg/mocks/jetstream_stream.go deleted file mode 100644 index 1f283a6e..00000000 --- a/internal/pkg/mocks/jetstream_stream.go +++ /dev/null @@ -1,274 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: github.com/nats-io/nats.go/jetstream (interfaces: Stream) -// -// Generated by this command: -// -// mockgen --destination ../../../internal/pkg/mocks/jetstream_stream.go --package mocks github.com/nats-io/nats.go/jetstream Stream -// - -// Package mocks is a generated GoMock package. -package mocks - -import ( - context "context" - reflect "reflect" - - jetstream "github.com/nats-io/nats.go/jetstream" - gomock "go.uber.org/mock/gomock" -) - -// MockStream is a mock of Stream interface. -type MockStream struct { - ctrl *gomock.Controller - recorder *MockStreamMockRecorder -} - -// MockStreamMockRecorder is the mock recorder for MockStream. -type MockStreamMockRecorder struct { - mock *MockStream -} - -// NewMockStream creates a new mock instance. -func NewMockStream(ctrl *gomock.Controller) *MockStream { - mock := &MockStream{ctrl: ctrl} - mock.recorder = &MockStreamMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockStream) EXPECT() *MockStreamMockRecorder { - return m.recorder -} - -// CachedInfo mocks base method. -func (m *MockStream) CachedInfo() *jetstream.StreamInfo { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CachedInfo") - ret0, _ := ret[0].(*jetstream.StreamInfo) - return ret0 -} - -// CachedInfo indicates an expected call of CachedInfo. -func (mr *MockStreamMockRecorder) CachedInfo() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CachedInfo", reflect.TypeOf((*MockStream)(nil).CachedInfo)) -} - -// Consumer mocks base method. -func (m *MockStream) Consumer(arg0 context.Context, arg1 string) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Consumer", arg0, arg1) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Consumer indicates an expected call of Consumer. -func (mr *MockStreamMockRecorder) Consumer(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Consumer", reflect.TypeOf((*MockStream)(nil).Consumer), arg0, arg1) -} - -// ConsumerNames mocks base method. -func (m *MockStream) ConsumerNames(arg0 context.Context) jetstream.ConsumerNameLister { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ConsumerNames", arg0) - ret0, _ := ret[0].(jetstream.ConsumerNameLister) - return ret0 -} - -// ConsumerNames indicates an expected call of ConsumerNames. -func (mr *MockStreamMockRecorder) ConsumerNames(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ConsumerNames", reflect.TypeOf((*MockStream)(nil).ConsumerNames), arg0) -} - -// CreateConsumer mocks base method. -func (m *MockStream) CreateConsumer(arg0 context.Context, arg1 jetstream.ConsumerConfig) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateConsumer", arg0, arg1) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateConsumer indicates an expected call of CreateConsumer. -func (mr *MockStreamMockRecorder) CreateConsumer(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateConsumer", reflect.TypeOf((*MockStream)(nil).CreateConsumer), arg0, arg1) -} - -// CreateOrUpdateConsumer mocks base method. -func (m *MockStream) CreateOrUpdateConsumer(arg0 context.Context, arg1 jetstream.ConsumerConfig) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "CreateOrUpdateConsumer", arg0, arg1) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// CreateOrUpdateConsumer indicates an expected call of CreateOrUpdateConsumer. -func (mr *MockStreamMockRecorder) CreateOrUpdateConsumer(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateConsumer", reflect.TypeOf((*MockStream)(nil).CreateOrUpdateConsumer), arg0, arg1) -} - -// DeleteConsumer mocks base method. -func (m *MockStream) DeleteConsumer(arg0 context.Context, arg1 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteConsumer", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteConsumer indicates an expected call of DeleteConsumer. -func (mr *MockStreamMockRecorder) DeleteConsumer(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteConsumer", reflect.TypeOf((*MockStream)(nil).DeleteConsumer), arg0, arg1) -} - -// DeleteMsg mocks base method. -func (m *MockStream) DeleteMsg(arg0 context.Context, arg1 uint64) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteMsg", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteMsg indicates an expected call of DeleteMsg. -func (mr *MockStreamMockRecorder) DeleteMsg(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteMsg", reflect.TypeOf((*MockStream)(nil).DeleteMsg), arg0, arg1) -} - -// GetLastMsgForSubject mocks base method. -func (m *MockStream) GetLastMsgForSubject(arg0 context.Context, arg1 string) (*jetstream.RawStreamMsg, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetLastMsgForSubject", arg0, arg1) - ret0, _ := ret[0].(*jetstream.RawStreamMsg) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetLastMsgForSubject indicates an expected call of GetLastMsgForSubject. -func (mr *MockStreamMockRecorder) GetLastMsgForSubject(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetLastMsgForSubject", reflect.TypeOf((*MockStream)(nil).GetLastMsgForSubject), arg0, arg1) -} - -// GetMsg mocks base method. -func (m *MockStream) GetMsg(arg0 context.Context, arg1 uint64, arg2 ...jetstream.GetMsgOpt) (*jetstream.RawStreamMsg, error) { - m.ctrl.T.Helper() - varargs := []any{arg0, arg1} - for _, a := range arg2 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "GetMsg", varargs...) - ret0, _ := ret[0].(*jetstream.RawStreamMsg) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetMsg indicates an expected call of GetMsg. -func (mr *MockStreamMockRecorder) GetMsg(arg0, arg1 any, arg2 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0, arg1}, arg2...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMsg", reflect.TypeOf((*MockStream)(nil).GetMsg), varargs...) -} - -// Info mocks base method. -func (m *MockStream) Info(arg0 context.Context, arg1 ...jetstream.StreamInfoOpt) (*jetstream.StreamInfo, error) { - m.ctrl.T.Helper() - varargs := []any{arg0} - for _, a := range arg1 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Info", varargs...) - ret0, _ := ret[0].(*jetstream.StreamInfo) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// Info indicates an expected call of Info. -func (mr *MockStreamMockRecorder) Info(arg0 any, arg1 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0}, arg1...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Info", reflect.TypeOf((*MockStream)(nil).Info), varargs...) -} - -// ListConsumers mocks base method. -func (m *MockStream) ListConsumers(arg0 context.Context) jetstream.ConsumerInfoLister { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ListConsumers", arg0) - ret0, _ := ret[0].(jetstream.ConsumerInfoLister) - return ret0 -} - -// ListConsumers indicates an expected call of ListConsumers. -func (mr *MockStreamMockRecorder) ListConsumers(arg0 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListConsumers", reflect.TypeOf((*MockStream)(nil).ListConsumers), arg0) -} - -// OrderedConsumer mocks base method. -func (m *MockStream) OrderedConsumer(arg0 context.Context, arg1 jetstream.OrderedConsumerConfig) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "OrderedConsumer", arg0, arg1) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// OrderedConsumer indicates an expected call of OrderedConsumer. -func (mr *MockStreamMockRecorder) OrderedConsumer(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "OrderedConsumer", reflect.TypeOf((*MockStream)(nil).OrderedConsumer), arg0, arg1) -} - -// Purge mocks base method. -func (m *MockStream) Purge(arg0 context.Context, arg1 ...jetstream.StreamPurgeOpt) error { - m.ctrl.T.Helper() - varargs := []any{arg0} - for _, a := range arg1 { - varargs = append(varargs, a) - } - ret := m.ctrl.Call(m, "Purge", varargs...) - ret0, _ := ret[0].(error) - return ret0 -} - -// Purge indicates an expected call of Purge. -func (mr *MockStreamMockRecorder) Purge(arg0 any, arg1 ...any) *gomock.Call { - mr.mock.ctrl.T.Helper() - varargs := append([]any{arg0}, arg1...) - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Purge", reflect.TypeOf((*MockStream)(nil).Purge), varargs...) -} - -// SecureDeleteMsg mocks base method. -func (m *MockStream) SecureDeleteMsg(arg0 context.Context, arg1 uint64) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SecureDeleteMsg", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// SecureDeleteMsg indicates an expected call of SecureDeleteMsg. -func (mr *MockStreamMockRecorder) SecureDeleteMsg(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SecureDeleteMsg", reflect.TypeOf((*MockStream)(nil).SecureDeleteMsg), arg0, arg1) -} - -// UpdateConsumer mocks base method. -func (m *MockStream) UpdateConsumer(arg0 context.Context, arg1 jetstream.ConsumerConfig) (jetstream.Consumer, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateConsumer", arg0, arg1) - ret0, _ := ret[0].(jetstream.Consumer) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// UpdateConsumer indicates an expected call of UpdateConsumer. -func (mr *MockStreamMockRecorder) UpdateConsumer(arg0, arg1 any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateConsumer", reflect.TypeOf((*MockStream)(nil).UpdateConsumer), arg0, arg1) -} diff --git a/pkg/microservice/messaging/messaging.go b/pkg/microservice/messaging/messaging.go index ddec9475..c3c21d92 100644 --- a/pkg/microservice/messaging/messaging.go +++ b/pkg/microservice/messaging/messaging.go @@ -3,113 +3,99 @@ package messaging import ( "time" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" "github.com/nats-io/nats.go" - "github.com/nats-io/nats.go/jetstream" ) -const ( - maxReconnects = 5000 - reconnectWait = 10 * time.Second - reconnectJitterNoTLS = 500 * time.Millisecond - reconnectJitterTLS = 2 * time.Second - reconnectBuffer = 1024 * 1024 * 10 -) - -type ResolvedService struct { - ID string - Address string - Port int -} - -type Broker interface { - CreatePersistentMessageStore(name string, subjects []string) (jetstream.Stream, error) - CreatePersistentMessageReceiver(name, id, address, port, ctype string, stream jetstream.Stream) (jetstream.Consumer, error) - RetrieveRegisteredConsumers(stream jetstream.Stream) ([]ResolvedService, error) - PersistedPublish(topic string, payload []byte) error - Consume(consumer jetstream.Consumer, handler func(msg jetstream.Msg)) (jetstream.ConsumeContext, error) - Subscribe(topic string, callback nats.MsgHandler) error - QueueGroupSubscribe(topic, queue string, callback nats.MsgHandler) error - Publish(topic string, payload []byte) error - PublishSync(topic string, payload []byte, timeout time.Duration) (*nats.Msg, error) - Unsubscribe(topic string) error - Close() error -} - type MessageBroker struct { - url string - userName string - password string + URL string + Username string + Password string - broker Broker - stream jetstream.Stream - consumer jetstream.Consumer + NatsConnection *nats.Conn + subscriptions []*nats.Subscription } -func NewMessageBroker(url, userName, password, serviceName string) (*MessageBroker, error) { - broker, err := newNatsBroker(url, userName, password, serviceName) - if err != nil { - return nil, err - } +func (mb *MessageBroker) StartMessageBrokerConnection(servicename string) { + const ( + maxreconnects = 5000 + reconnectwait = 10 * time.Second + reconnectjitternotls = 500 * time.Millisecond + reconnectjittertls = 2 * time.Second + reconnectbuffer = 1024 * 1024 * 10 + ) - return &MessageBroker{url: url, userName: userName, password: password, broker: broker}, nil -} + var err error -func (mb *MessageBroker) CloseConnection() error { - return mb.broker.Close() -} + var clientname nats.Option -func (mb *MessageBroker) SubscribeAsync(topic string, callback nats.MsgHandler) error { - return mb.broker.Subscribe(topic, callback) -} + var auth nats.Option -func (mb *MessageBroker) SubscribeQueueAsync(topic string, queue string, callback nats.MsgHandler) error { - return mb.broker.QueueGroupSubscribe(topic, queue, callback) -} + clientname = nats.Name(servicename) -func (mb *MessageBroker) DesubscribeAsync(topic string) error { - return mb.broker.Unsubscribe(topic) -} + if mb.Username != "" && mb.Password != "" { + auth = nats.UserInfo(mb.Username, mb.Password) + } -func (mb *MessageBroker) Publish(topic string, payload []byte) error { - return mb.broker.Publish(topic, payload) + mb.NatsConnection, err = nats.Connect(mb.URL, auth, clientname, nats.MaxReconnects(maxreconnects), nats.ReconnectWait(reconnectwait), nats.ReconnectJitter(reconnectjitternotls, reconnectjittertls), nats.ReconnectBufSize(reconnectbuffer)) + if err != nil { + logger.FatalErrLog(err) + } } -func (mb *MessageBroker) PublishRequestAndWait(topic string, payload []byte, timeout time.Duration) (*nats.Msg, error) { - return mb.broker.PublishSync(topic, payload, timeout) -} +func (mb *MessageBroker) CloseConnection() { + for _, subscription := range mb.subscriptions { + err := subscription.Unsubscribe() + if err != nil { + logger.FatalErrLog(err) + } + } -func (mb *MessageBroker) RetrieveRegisteredConsumers(stream jetstream.Stream) ([]ResolvedService, error) { - return mb.broker.RetrieveRegisteredConsumers(stream) + mb.NatsConnection.Close() } -func (mb *MessageBroker) CreatePersistentMessageStore(name string, subjects []string) (jetstream.Stream, error) { - return mb.broker.CreatePersistentMessageStore(name, subjects) -} +func (mb *MessageBroker) SubscribeAsync(topic string, callback nats.MsgHandler) { + subscription, err := mb.NatsConnection.Subscribe(topic, callback) + if err != nil { + logger.FatalErrLog(err) + } -func (mb *MessageBroker) CreatePersistentMessageReceiver(name, id, address, port, cType string, stream jetstream.Stream) (jetstream.Consumer, error) { - return mb.broker.CreatePersistentMessageReceiver(name, id, address, port, cType, stream) + mb.subscriptions = append(mb.subscriptions, subscription) } -func (mb *MessageBroker) SetStream(stream jetstream.Stream) { - mb.stream = stream -} +func (mb *MessageBroker) SubscribeQueueAsync(topic string, queue string, callback nats.MsgHandler) { + subscription, err := mb.NatsConnection.QueueSubscribe(topic, queue, callback) + if err != nil { + logger.FatalErrLog(err) + } -func (mb *MessageBroker) GetStream() jetstream.Stream { - return mb.stream + mb.subscriptions = append(mb.subscriptions, subscription) } -func (mb *MessageBroker) SetConsumer(consumer jetstream.Consumer) { - mb.consumer = consumer +func (mb *MessageBroker) DeSubscribeAsync(topic string) { + subscriptions := mb.subscriptions + for _, subscription := range subscriptions { + if subscription.Subject == topic { + err := subscription.Unsubscribe() + if err != nil { + logger.FatalErrLog(err) + } + } + } } -func (mb *MessageBroker) GetConsumer() jetstream.Consumer { - return mb.consumer +func (mb *MessageBroker) Publish(topic string, payload []byte) { + err := mb.NatsConnection.Publish(topic, payload) + if err != nil { + logger.FatalErrLog(err) + } } -func (mb *MessageBroker) Consume(consumer jetstream.Consumer, handler func(msg jetstream.Msg)) (jetstream.ConsumeContext, error) { - return mb.broker.Consume(consumer, handler) -} +func (mb *MessageBroker) PublishRequestAndWait(topic string, payload []byte, timeout time.Duration) (*nats.Msg, error) { + msg, err := mb.NatsConnection.Request(topic, payload, timeout) + if err != nil { + return nil, err + } -func (mb *MessageBroker) PersistedPublish(topic string, payload []byte) error { - return mb.broker.PersistedPublish(topic, payload) + return msg, nil } diff --git a/pkg/microservice/messaging/nats.go b/pkg/microservice/messaging/nats.go deleted file mode 100644 index 4d800ca2..00000000 --- a/pkg/microservice/messaging/nats.go +++ /dev/null @@ -1,201 +0,0 @@ -package messaging - -import ( - "context" - "errors" - "strconv" - "time" - - "github.com/nats-io/nats.go" - "github.com/nats-io/nats.go/jetstream" -) - -var ErrorMetadataConfigIncomplete = errors.New("service metadata config incomplete") - -var _ Broker = &natsBroker{} - -type natsBroker struct { - natsConnection *nats.Conn - jetstreamManager jetstream.JetStream - subscriptions []*nats.Subscription - streams []jetstream.Stream - cancelFunctions []context.CancelFunc - consumer []jetstream.Consumer -} - -func newNatsBroker(url, userName, password, serviceName string) (Broker, error) { - natsOptions := make([]nats.Option, 0, 6) - - natsOptions = append(natsOptions, nats.Name(serviceName)) - natsOptions = append(natsOptions, nats.UserInfo(userName, password)) - natsOptions = append(natsOptions, nats.MaxReconnects(maxReconnects)) - natsOptions = append(natsOptions, nats.ReconnectWait(reconnectWait)) - natsOptions = append(natsOptions, nats.ReconnectJitter(reconnectJitterNoTLS, reconnectJitterTLS)) - natsOptions = append(natsOptions, nats.ReconnectBufSize(reconnectBuffer)) - - conn, err := nats.Connect(url, natsOptions...) - if err != nil { - return nil, err - } - - jsManager, err := jetstream.New(conn) - if err != nil { - return nil, err - } - - return &natsBroker{natsConnection: conn, jetstreamManager: jsManager}, nil -} - -// CreatePersistentMessageStore creates a jetstream stream. -func (nb *natsBroker) CreatePersistentMessageStore(name string, subjects []string) (jetstream.Stream, error) { - ctx, cancelFun := context.WithCancel(context.Background()) - - cfg := jetstream.StreamConfig{ - Name: name, - Subjects: subjects, - Retention: jetstream.LimitsPolicy, - MaxMsgs: 200, - Storage: jetstream.MemoryStorage, - } - - stream, err := nb.jetstreamManager.CreateOrUpdateStream(ctx, cfg) - - nb.streams = append(nb.streams, stream) - nb.cancelFunctions = append(nb.cancelFunctions, cancelFun) - - return stream, err -} - -// CreatePersistentMessageReceiver creates a jetstream consumer. -func (nb *natsBroker) CreatePersistentMessageReceiver(name, id, address, port, cType string, stream jetstream.Stream) (jetstream.Consumer, error) { - ctx, cancelFun := context.WithCancel(context.Background()) - - messageStartTime := time.Now().Add(-15 * time.Minute).Round(time.Minute) - - cfg := jetstream.ConsumerConfig{ - Name: name + id, - Durable: name + id, - InactiveThreshold: 8 * 24 * time.Hour, - DeliverPolicy: jetstream.DeliverByStartTimePolicy, - OptStartTime: &messageStartTime, - AckPolicy: jetstream.AckNonePolicy, - Metadata: map[string]string{"id": id, "address": address, "port": port, "type": cType}, - } - - consumer, err := stream.CreateOrUpdateConsumer(ctx, cfg) - - nb.consumer = append(nb.consumer, consumer) - nb.cancelFunctions = append(nb.cancelFunctions, cancelFun) - - return consumer, err -} - -// Close closes the connection to the broker and unsubscribes on all topics. -func (nb *natsBroker) Close() error { - for _, subscription := range nb.subscriptions { - if err := subscription.Unsubscribe(); err != nil { - return err - } - } - - for _, cancelFunc := range nb.cancelFunctions { - cancelFunc() - } - - nb.natsConnection.Close() - - return nil -} - -// Subscribe subscribes to a pubsub topic. -func (nb *natsBroker) Subscribe(topic string, callback nats.MsgHandler) error { - subscription, err := nb.natsConnection.Subscribe(topic, callback) - if err != nil { - return err - } - - nb.subscriptions = append(nb.subscriptions, subscription) - - return nil -} - -// QueueGroupSubscribe implements Broker. -func (nb *natsBroker) QueueGroupSubscribe(topic, group string, callback nats.MsgHandler) error { - subscription, err := nb.natsConnection.QueueSubscribe(topic, group, callback) - if err != nil { - return err - } - - nb.subscriptions = append(nb.subscriptions, subscription) - - return nil -} - -// Publish send a payload to a topic. -func (nb *natsBroker) Publish(topic string, payload []byte) error { - return nb.natsConnection.Publish(topic, payload) -} - -// PublishSync send a payload to a topic and wait for a reply. -func (nb *natsBroker) PublishSync(topic string, payload []byte, timeout time.Duration) (*nats.Msg, error) { - return nb.natsConnection.Request(topic, payload, timeout) -} - -// Unsubscribe unsubscribes from a pubsub topic. -func (nb *natsBroker) Unsubscribe(topic string) error { - for _, subscription := range nb.subscriptions { - if subscription.Subject != topic { - continue - } - if err := subscription.Unsubscribe(); err != nil { - return err - } - } - - return nil -} - -// RetrieveRegisteredConsumers returns registered consumers. -func (nb *natsBroker) RetrieveRegisteredConsumers(stream jetstream.Stream) ([]ResolvedService, error) { - serviceList := make([]ResolvedService, 0, 10) - - consumerList := stream.ListConsumers(context.TODO()) - for consumer := range consumerList.Info() { - cType, ok := consumer.Config.Metadata["type"] - if !ok || cType != "secondary" { - continue - } - - id, ok := consumer.Config.Metadata["id"] - if !ok { - return nil, ErrorMetadataConfigIncomplete - } - address, ok := consumer.Config.Metadata["address"] - if !ok { - return nil, ErrorMetadataConfigIncomplete - } - portString, ok := consumer.Config.Metadata["port"] - if !ok { - return nil, ErrorMetadataConfigIncomplete - } - - port, err := strconv.Atoi(portString) - if err != nil { - return nil, err - } - - serviceList = append(serviceList, ResolvedService{ID: id, Address: address, Port: port}) - } - - return serviceList, nil -} - -func (nb *natsBroker) Consume(consumer jetstream.Consumer, handler func(msg jetstream.Msg)) (jetstream.ConsumeContext, error) { - return consumer.Consume(handler) -} - -func (nb *natsBroker) PersistedPublish(topic string, payload []byte) (err error) { - _, err = nb.jetstreamManager.Publish(context.TODO(), topic, payload) - - return -} diff --git a/pkg/microservice/messaging/nats_test.go b/pkg/microservice/messaging/nats_test.go deleted file mode 100644 index 6f6043c0..00000000 --- a/pkg/microservice/messaging/nats_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package messaging - -import ( - "context" - "testing" - "time" - - "github.com/nameserver-systems/pdns-distribute/internal/pkg/mocks" - "github.com/nats-io/nats.go/jetstream" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "go.uber.org/mock/gomock" -) - -//go:generate mockgen --destination ../../../internal/pkg/mocks/jetstream.go --package mocks github.com/nats-io/nats.go/jetstream JetStream -//go:generate mockgen --destination ../../../internal/pkg/mocks/jetstream_stream.go --package mocks github.com/nats-io/nats.go/jetstream Stream -//go:generate mockgen --destination ../../../internal/pkg/mocks/jetstream_consumer_info_listener.go --package mocks github.com/nats-io/nats.go/jetstream ConsumerInfoLister -func Test_natsBroker_CreatePersistentMessageStore(t *testing.T) { - t.Run("successful", func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - expectedConfig := jetstream.StreamConfig{ - Name: "test-store", - Subjects: []string{"sub01", "sub02"}, - Retention: jetstream.LimitsPolicy, - MaxMsgs: 200, - Storage: jetstream.MemoryStorage, - } - - mockJetStreamManager := mocks.NewMockJetStream(ctrl) - mockJetStreamManager.EXPECT().CreateOrUpdateStream(gomock.Any(), expectedConfig).Return(nil, nil) - - nb := natsBroker{ - jetstreamManager: mockJetStreamManager, - } - - stream, err := nb.CreatePersistentMessageStore("test-store", []string{"sub01", "sub02"}) - - require.NoError(t, err) - assert.Nil(t, stream) - - assert.Len(t, nb.streams, 1) - assert.Len(t, nb.cancelFunctions, 1) - }) -} - -func Test_natsBroker_CreatePersistentMessageReceiver(t *testing.T) { - t.Run("successful", func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - messageStartTime := time.Now().Add(-15 * time.Minute).Round(time.Minute) - - expectedConfig := jetstream.ConsumerConfig{ - Name: "test-client", - DeliverPolicy: jetstream.DeliverByStartTimePolicy, - OptStartTime: &messageStartTime, - AckPolicy: jetstream.AckNonePolicy, - Metadata: map[string]string{"id": "0000", "address": "127.0.0.1", "port": "53", "type": "secondary"}, - } - - mockStream := mocks.NewMockStream(ctrl) - mockStream.EXPECT().CreateOrUpdateConsumer(gomock.Any(), expectedConfig).Return(nil, nil) - - nb := natsBroker{} - - consumer, err := nb.CreatePersistentMessageReceiver("test-client", "0000", "127.0.0.1", "53", "secondary", mockStream) - - require.NoError(t, err) - assert.Nil(t, consumer) - - assert.Len(t, nb.consumer, 1) - assert.Len(t, nb.cancelFunctions, 1) - }) -} - -func Test_natsBroker_PersistedPublish(t *testing.T) { - t.Run("success", func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockStream := mocks.NewMockJetStream(ctrl) - mockStream.EXPECT().Publish(context.TODO(), "top1", []byte("content")) - - nb := natsBroker{ - jetstreamManager: mockStream, - } - - err := nb.PersistedPublish("top1", []byte("content")) - - require.NoError(t, err) - }) -} - -func Test_natsBroker_RetrieveRegisteredConsumers(t *testing.T) { - t.Run("success-secondary", func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockInfoListener := mocks.NewMockConsumerInfoLister(ctrl) - mockInfoListener.EXPECT().Info().DoAndReturn(func() <-chan *jetstream.ConsumerInfo { - cf := make(chan *jetstream.ConsumerInfo, 2) - defer close(cf) - - cf <- &jetstream.ConsumerInfo{ - Config: jetstream.ConsumerConfig{ - Metadata: map[string]string{"type": "secondary", "id": "1", "address": "10.0.0.2", "port": "1234"}, - }, - } - - return cf - }) - - mockStream := mocks.NewMockStream(ctrl) - mockStream.EXPECT().ListConsumers(context.TODO()).Return(mockInfoListener) - - nb := natsBroker{} - list, err := nb.RetrieveRegisteredConsumers(mockStream) - - require.NoError(t, err) - assert.EqualValues(t, []ResolvedService{{ - ID: "1", - Address: "10.0.0.2", - Port: 1234, - }}, list) - }) - t.Run("success-primary", func(t *testing.T) { - ctrl := gomock.NewController(t) - defer ctrl.Finish() - - mockInfoListener := mocks.NewMockConsumerInfoLister(ctrl) - mockInfoListener.EXPECT().Info().DoAndReturn(func() <-chan *jetstream.ConsumerInfo { - cf := make(chan *jetstream.ConsumerInfo, 2) - defer close(cf) - - cf <- &jetstream.ConsumerInfo{ - Config: jetstream.ConsumerConfig{ - Metadata: map[string]string{"type": "primary", "id": "1", "address": "10.0.0.2", "port": "1234"}, - }, - } - - return cf - }) - - mockStream := mocks.NewMockStream(ctrl) - mockStream.EXPECT().ListConsumers(context.TODO()).Return(mockInfoListener) - - nb := natsBroker{} - list, err := nb.RetrieveRegisteredConsumers(mockStream) - - require.NoError(t, err) - assert.EqualValues(t, []ResolvedService{}, list) - }) -} diff --git a/pkg/microservice/microservice.go b/pkg/microservice/microservice.go index ea51d3e3..b6f9f543 100644 --- a/pkg/microservice/microservice.go +++ b/pkg/microservice/microservice.go @@ -10,6 +10,7 @@ import ( "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/messaging" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/metrics" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/servicediscovery" "github.com/nameserver-systems/pdns-distribute/pkg/microservice/utils" ) @@ -22,7 +23,10 @@ type Microservice struct { ServiceURL string - MessageBroker *messaging.MessageBroker + SDRegistration *servicediscovery.ServiceRegistration + ServiceDiscovery *servicediscovery.ServiceDiscovery + + MessageBroker messaging.MessageBroker Config *configuration.Configurationobject @@ -51,7 +55,11 @@ func (ms *Microservice) StartService() (err error) { ms.loadMicroserviceSettings() - err = ms.initializeMessageBroker(serviceidentifier) + ms.MessageBroker.StartMessageBrokerConnection(serviceidentifier) + + ms.prepareServiceRegistration() + ms.ServiceDiscovery, err = servicediscovery.StartServiceDiscoveryAndRegisterService(ms.SDRegistration) + if err != nil { return err } @@ -84,6 +92,8 @@ func generateServiceIdentifier(servicename string, ms *Microservice) string { func (ms *Microservice) initiateReferencedObjects() { const signalchannelsize = 2 + ms.SDRegistration = &servicediscovery.ServiceRegistration{} + ms.ServiceDiscovery = &servicediscovery.ServiceDiscovery{} ms.Config = &configuration.Configurationobject{} ms.SignalChannel = make(chan os.Signal, signalchannelsize) } @@ -94,19 +104,25 @@ func (ms *Microservice) loadMicroserviceSettings() { ms.Tags = append(ms.Tags, ms.Version) ms.Meta = ms.Config.GetStringMapSettings("ServiceMetaData") + ms.SDRegistration.ServiceDiscoveryURL = ms.Config.GetStringSetting("ServiceDiscovery.URL") + ms.SDRegistration.ServiceDiscoveryHealthPingIntervall = + ms.Config.GetTimeDuration("ServiceDiscovery.HealthPingIntervall") + + ms.MessageBroker.URL = ms.Config.GetStringSetting("MessageBroker.URL") + + ms.loadBasicAuthCredentialsSettings() + ms.checkAndSetDebugLogLevel() ms.checkAndStartMetricsEndpoint() } -func (ms *Microservice) initializeMessageBroker(serviceIdentifier string) (err error) { - brokerURL := ms.Config.GetStringSetting("MessageBroker.URL") - brokerUser := ms.Config.GetStringSetting("MessageBroker.Username") - brokerPassword := ms.Config.GetStringSetting("MessageBroker.Password") - - ms.MessageBroker, err = messaging.NewMessageBroker(brokerURL, brokerUser, brokerPassword, serviceIdentifier) +func (ms *Microservice) loadBasicAuthCredentialsSettings() { + ms.SDRegistration.ServiceDiscoveryUsername = ms.Config.GetStringSetting("ServiceDiscovery.Username") + ms.SDRegistration.ServiceDiscoveryPassword = ms.Config.GetStringSetting("ServiceDiscovery.Password") - return + ms.MessageBroker.Username = ms.Config.GetStringSetting("MessageBroker.Username") + ms.MessageBroker.Password = ms.Config.GetStringSetting("MessageBroker.Password") } func (ms *Microservice) checkAndSetDebugLogLevel() { @@ -124,20 +140,34 @@ func (ms *Microservice) checkAndStartMetricsEndpoint() { if prometheusaddress != "" { err := metrics.StartMetricsExporter(prometheusaddress) if err != nil { - logger.FatalErrLog(err) + logger.ErrorErrLog(err) } } }() } -func (ms *Microservice) generateServiceID() (err error) { - ms.ID, err = utils.GenerateUUID() +func (ms *Microservice) prepareServiceRegistration() { + ms.SDRegistration.MicroserviceID = ms.ID + ms.SDRegistration.MicroserviceName = ms.Name + ms.SDRegistration.MicroserviceTags = ms.Tags + ms.SDRegistration.MicroserviceMetadata = ms.Meta + ms.SDRegistration.MicroserviceURL = ms.ServiceURL +} + +func (ms *Microservice) generateServiceID() error { + uuid, err := utils.GenerateUUID() - return + ms.ID = uuid + + return err } func (ms *Microservice) CloseMicroservice() error { - return ms.MessageBroker.CloseConnection() + ms.MessageBroker.CloseConnection() + + err := ms.ServiceDiscovery.DeregisterService() + + return err } func (ms *Microservice) getCleanedServiceName() string { diff --git a/pkg/microservice/servicediscovery/errors.go b/pkg/microservice/servicediscovery/errors.go new file mode 100644 index 00000000..e5fb5c34 --- /dev/null +++ b/pkg/microservice/servicediscovery/errors.go @@ -0,0 +1,7 @@ +package servicediscovery + +import "errors" + +var ( + errNoURL = errors.New("ServiceDiscovery: No URL was set") +) diff --git a/pkg/microservice/servicediscovery/servicediscovery.go b/pkg/microservice/servicediscovery/servicediscovery.go new file mode 100644 index 00000000..7c09aaa9 --- /dev/null +++ b/pkg/microservice/servicediscovery/servicediscovery.go @@ -0,0 +1,296 @@ +package servicediscovery + +import ( + "net/url" + "time" + + "github.com/google/uuid" + consul "github.com/hashicorp/consul/api" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/logger" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/utils" + "github.com/shirou/gopsutil/v3/load" +) + +// ServiceDiscovery struct which holds connection. +type ServiceDiscovery struct { + serviceID string + + consulURL string + + consulBasicAuth *consul.HttpBasicAuth + ConsulClient *consul.Client + + serviceListenAddresses map[string]consul.ServiceAddress + serviceHealthCheck *consul.AgentServiceCheck +} + +// StartServiceDiscoveryAndRegisterService starts discovery connection ang registers service. +func StartServiceDiscoveryAndRegisterService(sr *ServiceRegistration) (*ServiceDiscovery, error) { + sd := &ServiceDiscovery{} + + err := sd.startServiceDiscoveryConnection(sr) + if err != nil { + return &ServiceDiscovery{}, err + } + + return sd, nil +} + +func (sd *ServiceDiscovery) startServiceDiscoveryConnection(sr *ServiceRegistration) error { + if !sr.isURLSet() { + return errNoURL + } + + sd.insertServiceRegistration(sr) + + if sr.ServiceDiscoveryUsername != "" && sr.ServiceDiscoveryPassword != "" { + sd.setServiceDiscoveryBasicAuthCredentials(sr.ServiceDiscoveryUsername, sr.ServiceDiscoveryPassword) + } + + servicereg, err := sr.generateServiceDiscoveryRegistration() + if err != nil { + return err + } + + addaddresserr := sd.addServiceListenAddress(sr.MicroserviceURL, "MainService") + if addaddresserr != nil { + return addaddresserr + } + + healthreg := generateHealthCheckRegistration(sr) + sd.setHealthCheck(healthreg) + + regerr := sd.registerService(servicereg) + + sd.startUpdateHealthCheckTTLHandler(sr) + + return regerr +} + +func (sd *ServiceDiscovery) startUpdateHealthCheckTTLHandler(sr *ServiceRegistration) { + healthcheckping := time.Tick(sr.ServiceDiscoveryHealthPingIntervall) //nolint:staticcheck + checkid := sd.serviceHealthCheck.CheckID + + go func() { + for range healthcheckping { + status := consul.HealthPassing + + if isLoadTooHigh() { + status = consul.HealthWarning + } + + updateerr := sd.ConsulClient.Agent().UpdateTTL(checkid, "", status) + if updateerr != nil { + logger.ErrorErrLog(updateerr) + } + } + }() +} + +func isLoadTooHigh() bool { + const highload = 10.0 + + actualload, loaderr := load.Avg() + if loaderr != nil { + logger.ErrorErrLog(loaderr) + } + + return actualload.Load1 > highload +} + +func (sd *ServiceDiscovery) insertServiceRegistration(sr *ServiceRegistration) { + sd.serviceID = sr.MicroserviceID + sd.consulURL = sr.ServiceDiscoveryURL +} + +func generateHealthCheckRegistration(sr *ServiceRegistration) *consul.AgentServiceCheck { + return &consul.AgentServiceCheck{ + CheckID: uuid.NewString(), + TTL: (sr.ServiceDiscoveryHealthPingIntervall * 3).String(), + DeregisterCriticalServiceAfter: (sr.ServiceDiscoveryHealthPingIntervall * 20).String(), + } +} + +func (sd *ServiceDiscovery) addServiceListenAddress(serviceurl string, description string) error { + if len(sd.serviceListenAddresses) == 0 { + sd.serviceListenAddresses = make(map[string]consul.ServiceAddress) + } + + svurl, err := url.Parse(serviceurl) + if err != nil { + return err + } + + numericport, convrsionerr := utils.ConvertStringToInt(svurl.Port()) + if convrsionerr != nil { + return convrsionerr + } + + sd.serviceListenAddresses[description] = consul.ServiceAddress{ + Address: svurl.Hostname(), + Port: numericport, + } + + return nil +} + +func (sd *ServiceDiscovery) setHealthCheck(healthCheck *consul.AgentServiceCheck) { + sd.serviceHealthCheck = healthCheck +} + +func (sd *ServiceDiscovery) isListenAddressesSet() bool { + return len(sd.serviceListenAddresses) != 0 +} + +func (sd *ServiceDiscovery) isClientInitiated() bool { + return sd.ConsulClient != nil +} + +func (sd *ServiceDiscovery) isHealthCheckSet() bool { + return sd.serviceHealthCheck != nil +} + +func (sd *ServiceDiscovery) registerService(serviceRegistration consul.AgentServiceRegistration) error { + clienterr := sd.newClient() + if clienterr != nil { + return clienterr + } + + if sd.isListenAddressesSet() { + sd.insertListenAddressesInRegistration(&serviceRegistration) + } + + if sd.isHealthCheckSet() { + sd.insertHealthCheckInRegistration(&serviceRegistration) + } + + registererr := sd.ConsulClient.Agent().ServiceRegister(&serviceRegistration) + if registererr != nil { + return registererr + } + + return nil +} + +// DeregisterService used with defer to deregister service if graceful shutdown. +func (sd *ServiceDiscovery) DeregisterService() error { + if sd.ConsulClient != nil { + err := sd.ConsulClient.Agent().ServiceDeregister(sd.serviceID) + if err != nil { + return err + } + } + + return nil +} + +func (sd *ServiceDiscovery) insertListenAddressesInRegistration(serviceRegistration *consul.AgentServiceRegistration) { + serviceRegistration.TaggedAddresses = sd.serviceListenAddresses +} + +func (sd *ServiceDiscovery) insertHealthCheckInRegistration(serviceRegistration *consul.AgentServiceRegistration) { + serviceRegistration.Check = sd.serviceHealthCheck +} + +func (sd *ServiceDiscovery) setServiceDiscoveryBasicAuthCredentials(username, password string) { + sd.consulBasicAuth = &consul.HttpBasicAuth{ + Username: username, + Password: password, + } +} + +func (sd *ServiceDiscovery) newClient() error { + if sd.isClientInitiated() { + return nil + } + + conf := consul.Config{ + Address: sd.consulURL, + } + + if sd.consulBasicAuth != nil { + conf.HttpAuth = sd.consulBasicAuth + } + + var err error + + sd.ConsulClient, err = consul.NewClient(&conf) + if err != nil { + return err + } + + return nil +} + +type ResolvedService struct { + ID string + Address string + Port int +} + +func (sd *ServiceDiscovery) GetServices(servicename, tag string) ([]ResolvedService, error) { + options := &consul.QueryOptions{} + + services, _, resolveerr := sd.ConsulClient.Health().Service(servicename, tag, false, options) + if resolveerr != nil { + return nil, resolveerr + } + + var resolvedservices []ResolvedService + + for _, service := range services { + state := service.Checks.AggregatedStatus() + if serviceStateIsAcceptable(state) { + resolvedservices = append(resolvedservices, ResolvedService{ + ID: service.Service.ID, + Address: service.Service.Address, + Port: service.Service.Port, + }) + } + } + + return resolvedservices, nil +} + +func serviceStateIsAcceptable(state string) bool { + return state == consul.HealthPassing || state == consul.HealthWarning +} + +func (sd *ServiceDiscovery) GetValue(key string) ([]byte, error) { + kvpair, _, err := sd.ConsulClient.KV().Get(key, nil) + + if kvpair == nil { + return []byte{}, err + } + + return kvpair.Value, err +} + +func (sd *ServiceDiscovery) PutValue(key string, value []byte) error { + _, err := sd.ConsulClient.KV().Put(&consul.KVPair{Key: key, Value: value}, nil) + + return err +} + +func (sd *ServiceDiscovery) SubscribeToKey(key string, valuechan chan<- []byte) { + actualIndex := uint64(0) + + go func() { + for { + kvpair, _, err := sd.ConsulClient.KV().Get(key, &consul.QueryOptions{WaitIndex: actualIndex}) + if err != nil { + logger.ErrorErrLog(err) + } + + valuechan <- kvpair.Value + + if actualIndex > kvpair.ModifyIndex { + actualIndex = 0 + + continue + } + + actualIndex = kvpair.ModifyIndex + } + }() +} diff --git a/pkg/microservice/servicediscovery/servicediscovery_test.go b/pkg/microservice/servicediscovery/servicediscovery_test.go new file mode 100644 index 00000000..09086505 --- /dev/null +++ b/pkg/microservice/servicediscovery/servicediscovery_test.go @@ -0,0 +1,155 @@ +//nolint:scopelint,lll,testpackage +package servicediscovery + +import ( + "testing" + + consul "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestServiceDiscovery_newClient(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sd := ServiceDiscovery{ + serviceID: "1234", + consulURL: "http://test.local:1234", + consulBasicAuth: &consul.HttpBasicAuth{}, + ConsulClient: nil, + serviceListenAddresses: map[string]consul.ServiceAddress{}, + serviceHealthCheck: &consul.AgentServiceCheck{}, + } + + err := sd.newClient() + + require.NoError(t, err) + }) + + t.Run("fail_client_exists", func(t *testing.T) { + sd := ServiceDiscovery{ + serviceID: "1234", + consulURL: "http://test.local:1234", + consulBasicAuth: &consul.HttpBasicAuth{}, + ConsulClient: &consul.Client{}, + serviceListenAddresses: map[string]consul.ServiceAddress{}, + serviceHealthCheck: &consul.AgentServiceCheck{}, + } + + err := sd.newClient() + + require.NoError(t, err) + }) +} + +func TestServiceDiscovery_isClientInitiated(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sd := ServiceDiscovery{ + ConsulClient: &consul.Client{}, + } + + actual := sd.isClientInitiated() + + assert.True(t, actual) + }) + + t.Run("fail", func(t *testing.T) { + sd := ServiceDiscovery{ + ConsulClient: nil, + } + + actual := sd.isClientInitiated() + + assert.False(t, actual) + }) +} + +func TestServiceDiscovery_setServiceDiscoveryBasicAuthCredentials(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sd := ServiceDiscovery{ + consulBasicAuth: &consul.HttpBasicAuth{}, + } + + sd.setServiceDiscoveryBasicAuthCredentials("TEST-USER", "1234") + + assert.EqualValues(t, "TEST-USER", sd.consulBasicAuth.Username) + assert.EqualValues(t, "1234", sd.consulBasicAuth.Password) + }) +} + +func TestServiceDiscovery_isHealthCheckSet(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sd := ServiceDiscovery{serviceHealthCheck: &consul.AgentServiceCheck{}} + + actual := sd.isHealthCheckSet() + + assert.True(t, actual) + }) + + t.Run("fail", func(t *testing.T) { + sd := ServiceDiscovery{} + + actual := sd.isHealthCheckSet() + + assert.False(t, actual) + }) +} + +func TestServiceDiscovery_isListenAddressesSet(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sd := ServiceDiscovery{serviceListenAddresses: map[string]consul.ServiceAddress{"test": {}}} + + actual := sd.isListenAddressesSet() + + assert.True(t, actual) + }) + + t.Run("fail", func(t *testing.T) { + sd := ServiceDiscovery{} + + actual := sd.isListenAddressesSet() + + assert.False(t, actual) + }) +} + +func TestServiceDiscovery_insertListenAddressesInRegistration(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sr := &consul.AgentServiceRegistration{TaggedAddresses: map[string]consul.ServiceAddress{}} + sd := ServiceDiscovery{} + + sd.insertListenAddressesInRegistration(sr) + + assert.IsType(t, map[string]consul.ServiceAddress{}, sd.serviceListenAddresses) + }) + + t.Run("fail", func(t *testing.T) { + sr := &consul.AgentServiceRegistration{} + sd := ServiceDiscovery{} + + sd.insertListenAddressesInRegistration(sr) + + assert.Empty(t, sd.serviceListenAddresses) + }) +} + +func TestServiceDiscovery_insertHealthCheckInRegistration(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sr := &consul.AgentServiceRegistration{Check: &consul.AgentServiceCheck{ + Name: "test", + }} + sd := ServiceDiscovery{} + + sd.insertHealthCheckInRegistration(sr) + + assert.IsType(t, &consul.AgentServiceCheck{}, sd.serviceHealthCheck) + }) + + t.Run("fail", func(t *testing.T) { + sr := &consul.AgentServiceRegistration{} + sd := ServiceDiscovery{} + + sd.insertHealthCheckInRegistration(sr) + + assert.Empty(t, sd.serviceListenAddresses) + }) +} diff --git a/pkg/microservice/servicediscovery/serviceregistration.go b/pkg/microservice/servicediscovery/serviceregistration.go new file mode 100644 index 00000000..ddd4f432 --- /dev/null +++ b/pkg/microservice/servicediscovery/serviceregistration.go @@ -0,0 +1,50 @@ +package servicediscovery + +import ( + "net/url" + "time" + + consul "github.com/hashicorp/consul/api" + "github.com/nameserver-systems/pdns-distribute/pkg/microservice/utils" +) + +// ServiceRegistration used for register service in service discovery. +type ServiceRegistration struct { + ServiceDiscoveryURL string + ServiceDiscoveryUsername string + ServiceDiscoveryPassword string + ServiceDiscoveryHealthPingIntervall time.Duration + + MicroserviceID string + MicroserviceName string + MicroserviceTags []string + MicroserviceMetadata map[string]string + MicroserviceURL string +} + +func (sr *ServiceRegistration) isURLSet() bool { + return sr.ServiceDiscoveryURL != "" +} + +func (sr *ServiceRegistration) generateServiceDiscoveryRegistration() (consul.AgentServiceRegistration, error) { + microserviceurl := sr.MicroserviceURL + + msurl, parseerr := url.Parse(microserviceurl) + if parseerr != nil { + return consul.AgentServiceRegistration{}, parseerr + } + + microserviceport, converterr := utils.ConvertStringToInt(msurl.Port()) + if converterr != nil { + return consul.AgentServiceRegistration{}, converterr + } + + return consul.AgentServiceRegistration{ + ID: sr.MicroserviceID, + Name: sr.MicroserviceName, + Tags: sr.MicroserviceTags, + Port: microserviceport, + Address: msurl.Hostname(), + Meta: sr.MicroserviceMetadata, + }, nil +} diff --git a/pkg/microservice/servicediscovery/serviceregistration_test.go b/pkg/microservice/servicediscovery/serviceregistration_test.go new file mode 100644 index 00000000..1c2a45e9 --- /dev/null +++ b/pkg/microservice/servicediscovery/serviceregistration_test.go @@ -0,0 +1,102 @@ +//nolint:funlen +package servicediscovery + +import ( + "testing" + + "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestServiceRegistration_generateServiceDiscoveryRegistration(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sr := ServiceRegistration{ + ServiceDiscoveryURL: "http://test.local:1234", + ServiceDiscoveryUsername: "", + ServiceDiscoveryPassword: "", + MicroserviceID: "a1b2-c3d4-e5f6", + MicroserviceName: "testservice", + MicroserviceTags: []string{"test", "test2"}, + MicroserviceMetadata: map[string]string{"test": "TEST"}, + MicroserviceURL: "http://test.local:4321", + } + + actual, err := sr.generateServiceDiscoveryRegistration() + + require.NoError(t, err) + require.NotNil(t, actual) + + assert.Equal(t, api.AgentServiceRegistration{ + ID: "a1b2-c3d4-e5f6", + Name: "testservice", + Tags: []string{"test", "test2"}, + Port: 4321, + Address: "test.local", + Meta: map[string]string{"test": "TEST"}, + }, actual) + }) + + t.Run("fail", func(t *testing.T) { + t.Run("url_parsing", func(t *testing.T) { + sr := ServiceRegistration{ + ServiceDiscoveryURL: "http://test.local:1234", + ServiceDiscoveryUsername: "", + ServiceDiscoveryPassword: "", + MicroserviceID: "a1b2-c3d4-e5f6", + MicroserviceName: "testservice", + MicroserviceTags: []string{"test", "test2"}, + MicroserviceMetadata: map[string]string{"test": "TEST"}, + MicroserviceURL: "http::://test.local:4321", + } + + actual, err := sr.generateServiceDiscoveryRegistration() + + require.Error(t, err) + require.NotNil(t, actual) + + assert.Equal(t, api.AgentServiceRegistration{}, actual) + }) + t.Run("port_parsing", func(t *testing.T) { + sr := ServiceRegistration{ + ServiceDiscoveryURL: "http://test.local:1234", + ServiceDiscoveryUsername: "", + ServiceDiscoveryPassword: "", + MicroserviceID: "a1b2-c3d4-e5f6", + MicroserviceName: "testservice", + MicroserviceTags: []string{"test", "test2"}, + MicroserviceMetadata: map[string]string{"test": "TEST"}, + MicroserviceURL: "http://test.local:43k21", + } + + actual, err := sr.generateServiceDiscoveryRegistration() + + require.Error(t, err) + require.NotNil(t, actual) + + assert.Equal(t, api.AgentServiceRegistration{}, actual) + }) + }) +} + +func TestServiceRegistration_isURLSet(t *testing.T) { + t.Run("ok", func(t *testing.T) { + sr := ServiceRegistration{ + ServiceDiscoveryURL: "http://test.local", + } + + actual := sr.isURLSet() + + assert.True(t, actual) + }) + + t.Run("fail", func(t *testing.T) { + sr := ServiceRegistration{ + ServiceDiscoveryURL: "", + } + + actual := sr.isURLSet() + + assert.False(t, actual) + }) +}