Compare commits

...

16 Commits

Author SHA1 Message Date
bakito
4a38df1b59 chore: update goreleaser 2025-07-13 09:18:00 +02:00
Marc Brugger
9ec5c0412e add new logo (#603) 2025-07-13 08:23:12 +02:00
ElevenNotes
01676e12f3 feat: add unauthorized health check based on status (if all success = http OK) (#601)
* feat: add unauthorized health check based on status (if all success = http OK)

* feat: ignore v or other non-numerical version affixes and suffixes

* fix: syntax

* fix: add head not just get
2025-07-10 22:33:46 +02:00
Marc Brugger
78f7d08398 test: add rewrites for e2e test (#600) 2025-07-05 09:25:56 +02:00
bakito-renovate[bot]
11d4d14f4d chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.2.1 (#598)
* chore(deps): update module github.com/golangci/golangci-lint/v2 to v2.2.1

* ignore revive var-naming

---------

Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
Co-authored-by: bakito <github@bakito.ch>
2025-06-30 20:36:54 +02:00
bakito-renovate[bot]
ff91f4873a chore(deps): update dependency adguardteam/adguardhome to v0.107.63 (#597)
Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
2025-06-27 16:43:31 +02:00
bakito-renovate[bot]
778bf7b516 chore(deps): update module k8s.io/apimachinery to v0.33.2 (#596)
Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
2025-06-23 06:53:46 +02:00
bakito
cce24c1223 docs: add icon to readme 2025-06-19 09:28:38 +02:00
Ted Jangius
b4fabf687b Add logo (#595) 2025-06-18 21:57:16 +02:00
Joseph Williams
74ae6a9096 Docs: Clarify initial setup instructions for origin and replicas (#593)
* Disambiguate 'Prerequisites' section in README.md

* Correct  part of speech error in 'Prerequisite' section in README.md
2025-06-12 23:48:16 +02:00
bakito-renovate[bot]
92129ab069 chore(deps): update k8s.io/utils digest to 4c0f3b2 (#590)
Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
2025-06-09 07:59:24 +02:00
bakito-renovate[bot]
d7f50086c3 chore(deps): update module github.com/goreleaser/goreleaser/v2 to v2.10.2 (#591)
Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
2025-06-09 07:59:11 +02:00
bakito-renovate[bot]
50f883337a chore(deps): update module golang.org/x/mod to v0.25.0 (#592)
Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
2025-06-09 07:58:52 +02:00
bakito-renovate[bot]
5a35f7c9d1 chore(deps): update dependency adguardteam/adguardhome to v0.107.62 (#589)
Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
2025-06-01 13:06:59 +02:00
bakito-renovate[bot]
1b1a712a65 chore(deps): update module github.com/santhosh-tekuri/jsonschema/v6 to v6.0.2 (#588)
Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
2025-05-24 11:02:28 +02:00
bakito-renovate[bot]
724a20e47e chore(deps): update module github.com/gin-gonic/gin to v1.10.1 (#587)
Co-authored-by: bakito-renovate[bot] <205501741+bakito-renovate[bot]@users.noreply.github.com>
2025-05-24 11:02:17 +02:00
15 changed files with 474 additions and 39 deletions

View File

@@ -51,6 +51,7 @@ jobs:
- name: Send coverage
if: runner.os == 'Linux'
uses: shogo82148/actions-goveralls@v1
continue-on-error: true
with:
path-to-profile: coverage.out

View File

@@ -162,6 +162,8 @@ linters:
disabled: true
- name: unused-receiver
disabled: true
- name: var-naming
disabled: true
staticcheck:
checks:
- 'all'

View File

@@ -25,11 +25,11 @@ TB_CONTROLLER_GEN_VERSION ?= v0.18.0
# renovate: packageName=mvdan.cc/gofumpt
TB_GOFUMPT_VERSION ?= v0.8.0
# renovate: packageName=github.com/golangci/golangci-lint/v2
TB_GOLANGCI_LINT_VERSION ?= v2.1.6
TB_GOLANGCI_LINT_VERSION ?= v2.2.2
# renovate: packageName=github.com/segmentio/golines
TB_GOLINES_VERSION ?= v0.12.2
# renovate: packageName=github.com/goreleaser/goreleaser/v2
TB_GORELEASER_VERSION ?= v2.9.0
TB_GORELEASER_VERSION ?= v2.11.0
# renovate: packageName=go.uber.org/mock/mockgen
TB_MOCKGEN_VERSION ?= v0.5.2
# renovate: packageName=github.com/oapi-codegen/oapi-codegen/v2

View File

@@ -74,7 +74,7 @@ kind-test:
@./testdata/e2e/bin/install-chart.sh
# renovate: packageName=AdguardTeam/AdGuardHome
ADGUARD_HOME_VERSION ?= v0.107.61
ADGUARD_HOME_VERSION ?= v0.107.63
model: tb.oapi-codegen
@mkdir -p tmp

View File

@@ -3,7 +3,9 @@
[![Go Report Card](https://goreportcard.com/badge/github.com/bakito/adguardhome-sync)](https://goreportcard.com/report/github.com/bakito/adguardhome-sync)
[![Coverage Status](https://coveralls.io/repos/github/bakito/adguardhome-sync/badge.svg?branch=main&service=github)](https://coveralls.io/github/bakito/adguardhome-sync?branch=main)
# AdGuardHome sync
# <img src="./media/adguardhome-sync.svg" alt="AdGuardHome sync" width="50"/> AdGuardHome sync
Synchronize [AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) config to replica instances.
@@ -43,7 +45,7 @@ go install github.com/bakito/adguardhome-sync@latest
## Prerequisites
Both the origin instance must be initially setup via the AdguardHome installation wizard.
Both the origin instance and replica(s) must be initially set up with AdguardHome via the AdguardHome installation wizard.
## Username / Password vs. Cookie

10
go.mod
View File

@@ -4,7 +4,7 @@ go 1.24.2
require (
github.com/caarlos0/env/v11 v11.3.1
github.com/gin-gonic/gin v1.10.0
github.com/gin-gonic/gin v1.10.1
github.com/go-faker/faker/v4 v4.6.1
github.com/go-resty/resty/v2 v2.16.5
github.com/google/uuid v1.6.0
@@ -14,14 +14,14 @@ require (
github.com/onsi/gomega v1.37.0
github.com/prometheus/client_golang v1.22.0
github.com/robfig/cron/v3 v3.0.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2
github.com/spf13/cobra v1.9.1
go.uber.org/mock v0.5.2
go.uber.org/zap v1.27.0
golang.org/x/mod v0.24.0
golang.org/x/mod v0.25.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/apimachinery v0.33.1
k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979
k8s.io/apimachinery v0.33.2
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
)
require (

20
go.sum
View File

@@ -28,8 +28,8 @@ github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBv
github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w=
github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ=
github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-faker/faker/v4 v4.6.1 h1:xUyVpAjEtB04l6XFY0V/29oR332rOSPWV4lU8RwDt4k=
github.com/go-faker/faker/v4 v4.6.1/go.mod h1:arSdxNCSt7mOhdk8tEolvHeIJ7eX4OX80wXjKKvkKBY=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
@@ -115,8 +115,8 @@ github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzG
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1 h1:PKK9DyHxif4LZo+uQSgXNqs0jj5+xZwwfKHgph2lxBw=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2 h1:KRzFb2m7YtdldCEkzs6KqmJw4nqEVZGK7IN2kJkjTuQ=
github.com/santhosh-tekuri/jsonschema/v6 v6.0.2/go.mod h1:JXeL+ps8p7/KNMjDQk3TCwPpBy0wYklyWTfbkIzdIFU=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
@@ -159,8 +159,8 @@ golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -202,12 +202,12 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
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=
k8s.io/apimachinery v0.33.1 h1:mzqXWV8tW9Rw4VeW9rEkqvnxj59k1ezDUl20tFK/oM4=
k8s.io/apimachinery v0.33.1/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/apimachinery v0.33.2 h1:IHFVhqg59mb8PJWTLi8m1mAoepkUNYmptHsV+Z1m5jY=
k8s.io/apimachinery v0.33.2/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979 h1:jgJW5IePPXLGB8e/1wvd0Ich9QE97RvvF3a8J3fP/Lg=
k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=

190
media/adguardhome-sync.svg Normal file
View File

@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.2"
viewBox="0 0 1000 1000"
id="svg3"
sodipodi:docname="adguardhome-sync.svg"
inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs3">
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
is_visible="true"
lpeversion="1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect18"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,54.646215,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,54.646212,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="skeletal"
id="path-effect13"
is_visible="true"
lpeversion="1"
pattern="m 78.30448,0.02132 c -1.76356,0.0996 -3.48821,0.55822 -5.06836,1.34765 L 5.80252,35.08773 c -18.554321,9.281429 -18.766576,9.393634 0,18.78124 l 67.4336,33.71876 c 8.62996,4.31519 18.78393,-1.9607 18.7832,-11.60938 v -11.5 h 213 c 6.62742,0 12,-5.372583 12,-12 v -16 c 0,-6.627417 -5.37258,-12 -12,-12 h -213 v -11.5 C 92.01887,5.52137 85.74946,-0.40162 78.30448,0.02132 Z"
copytype="repeated_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="100"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
hide_knot="false"
fuse_tolerance="0"
pattern-nodetypes="cccccccssssccc" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect11"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,12,0,1 @ F,0,1,1,0,12,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect33"
is_visible="true"
lpeversion="1"
nodesatellites_param=""
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<linearGradient
id="swatch26"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop26" />
</linearGradient>
<linearGradient
id="swatch25"
inkscape:swatch="solid">
<stop
style="stop-color:#407b28;stop-opacity:1;"
offset="0"
id="stop25" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 500 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1000 : 500 : 1"
inkscape:persp3d-origin="500 : 333.33333 : 1"
id="perspective6" />
<inkscape:path-effect
effect="skeletal"
id="path-effect13-9"
is_visible="true"
lpeversion="1"
pattern="m -435.41689,700.31394 -82.73956,27.87776 82.73956,31.49534 v -23.8092 l 434.54687,9.11337 v -33.59902 l -434.54687,9.11337 z"
copytype="repeated_stretched"
prop_scale="2"
scale_y_rel="false"
spacing="100"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
hide_knot="false"
fuse_tolerance="0"
pattern-nodetypes="sccccccs" />
</defs>
<sodipodi:namedview
id="namedview3"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="0.70710678"
inkscape:cx="540.93669"
inkscape:cy="502.04582"
inkscape:window-width="1556"
inkscape:window-height="1360"
inkscape:window-x="1868"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg3" />
<path
fill="#68bc71"
d="m 993.75002,114.1 c 0,171.8 3.1,595.3 -493.8,885.9 C 3.0500233,709.4 6.2500233,285.9 6.2500233,114.1 159.35002,35.9 345.25002,0 499.95002,0 c 154.7,0 340.6,35.9 493.8,114.1 z"
id="path1"
inkscape:label="shield" />
<path
fill="#67b279"
d="M500 1000C3.1 709.4 6.2 285.9 6.2 114.1 159.4 35.9 345.3 0 500 0z"
id="path2"
inkscape:label="half-shield" />
<path
fill="#ffffff"
d="m 225,449.6 c 15,-11.7 80,-53.4 128.3,1.6 L 453.3,569.6 720,297.9 c 11.7,-10 31.7,-23.3 55,-5 L 455,716.2 Z"
id="path3"
inkscape:label="checkmark"
style="display:none" />
<circle
style="display:none;fill:#ffffff;fill-opacity:0.5;stroke:#ffffff;stroke-width:8e-08;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:100;stroke-dasharray:none;stroke-opacity:0.502604"
id="path18"
cx="-500"
cy="426"
r="400"
inkscape:label="badge"
transform="scale(-1,1)" />
<path
id="path12-8"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.00001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:100;stroke-dasharray:none;stroke-opacity:1"
d="m -75.867249,555.75073 c -1.469322,-39.92741 -12.296964,-76.43624 -30.823861,-104.61661 -21.05517,28.18037 -47.89663,45.38022 -75.18829,53.68483 l 42.51192,20.42415 c -33.35434,61.94297 -101.60764,105.3289 -167.51689,101.23666 -42.42317,-1.43193 -82.3318,-22.18867 -112.01355,-52.33871 -21.09944,-21.43232 -53.37423,-31.44115 -79.38397,-16.1329 l -10.3958,6.11853 c 43.49744,68.86447 120.54256,113.80911 201.79332,112.04834 87.97224,-4.41047 162.60077,-62.73987 194.96448,-137.74518 z M -537.90127,346.51705 c 1.46924,39.92741 12.29681,76.43626 30.82364,104.61667 21.05523,-28.18031 47.89674,-45.38011 75.18842,-53.68467 l -42.51189,-20.42423 c 33.35441,-61.94281 101.60759,-105.32857 167.51673,-101.23635 42.4233,1.43194 82.33203,22.18879 112.01381,52.33897 21.0994,21.43235 53.37417,31.44124 79.38393,16.13305 l 10.39581,-6.11852 c -43.49739,-68.86468 -120.54264,-113.8095 -201.79355,-112.04872 -87.97208,4.41046 -162.60049,62.73965 -194.96429,137.74477 z"
transform="matrix(0,-1.3167476,1.3167476,0,-94.029776,21.910887)"
inkscape:label="double-arrow"
inkscape:path-effect="#path-effect1"
inkscape:original-d="m -75.867249,555.75073 c -1.469322,-39.92741 -12.296964,-76.43624 -30.823861,-104.61661 -21.05517,28.18037 -47.89663,45.38022 -75.18829,53.68483 l 42.51192,20.42415 c -33.35434,61.94297 -101.60764,105.3289 -167.51689,101.23666 -42.42317,-1.43193 -82.3318,-22.18867 -112.01355,-52.33871 -21.09944,-21.43232 -53.37423,-31.44115 -79.38397,-16.1329 l -10.3958,6.11853 c 43.49744,68.86447 120.54256,113.80911 201.79332,112.04834 87.97224,-4.41047 162.60077,-62.73987 194.96448,-137.74518 z M -537.90127,346.51705 c 1.46924,39.92741 12.29681,76.43626 30.82364,104.61667 21.05523,-28.18031 47.89674,-45.38011 75.18842,-53.68467 l -42.51189,-20.42423 c 33.35441,-61.94281 101.60759,-105.32857 167.51673,-101.23635 42.4233,1.43194 82.33203,22.18879 112.01381,52.33897 21.0994,21.43235 53.37417,31.44124 79.38393,16.13305 l 10.39581,-6.11852 c -43.49739,-68.86468 -120.54264,-113.8095 -201.79355,-112.04872 -87.97208,4.41046 -162.60049,62.73965 -194.96429,137.74477 z" />
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@@ -26,6 +26,8 @@ var (
index []byte
//go:embed favicon.ico
favicon []byte
//go:embed logo.svg
logo []byte
)
func (w *worker) handleSync(c *gin.Context) {
@@ -74,6 +76,10 @@ func (w *worker) handleFavicon(c *gin.Context) {
c.Data(http.StatusOK, "image/x-icon", favicon)
}
func (w *worker) handleLogo(c *gin.Context) {
c.Data(http.StatusOK, "image/svg+xml", logo)
}
func (w *worker) handleLogs(c *gin.Context) {
c.Data(http.StatusOK, "text/plain", []byte(strings.Join(log.Logs(), "")))
}
@@ -87,6 +93,10 @@ func (w *worker) handleStatus(c *gin.Context) {
c.JSON(http.StatusOK, w.status())
}
func (w *worker) handleHealthz(c *gin.Context) {
c.Status(w.healthz())
}
func (w *worker) listenAndServe() {
sl := l.With("port", w.cfg.API.Port)
if w.cfg.API.TLS.Enabled() {
@@ -100,9 +110,28 @@ func (w *worker) listenAndServe() {
gin.SetMode(gin.ReleaseMode)
r := gin.New()
r.Use(gin.Recovery())
r.HEAD("/healthz", w.handleHealthz)
r.GET("/healthz", w.handleHealthz)
var group gin.IRouter = r
if w.cfg.API.Username != "" && w.cfg.API.Password != "" {
r.Use(gin.BasicAuth(map[string]string{w.cfg.API.Username: w.cfg.API.Password}))
group = r.Group("/", gin.BasicAuth(map[string]string{w.cfg.API.Username: w.cfg.API.Password}))
}
group.POST("/api/v1/sync", w.handleSync)
group.GET("/api/v1/logs", w.handleLogs)
group.POST("/api/v1/clear-logs", w.handleClearLogs)
group.GET("/api/v1/status", w.handleStatus)
group.GET("/favicon.ico", w.handleFavicon)
group.GET("/logo.svg", w.handleLogo)
group.GET("/", w.handleRoot)
if w.cfg.API.Metrics.Enabled {
group.GET("/metrics", metrics.Handler())
go w.startScraping()
}
httpServer := &http.Server{
Addr: fmt.Sprintf(":%d", w.cfg.API.Port),
Handler: r,
@@ -111,17 +140,6 @@ func (w *worker) listenAndServe() {
}
r.SetHTMLTemplate(template.Must(template.New("index.html").Parse(string(index))))
r.POST("/api/v1/sync", w.handleSync)
r.GET("/api/v1/logs", w.handleLogs)
r.POST("/api/v1/clear-logs", w.handleClearLogs)
r.GET("/api/v1/status", w.handleStatus)
r.GET("/favicon.ico", w.handleFavicon)
r.GET("/", w.handleRoot)
if w.cfg.API.Metrics.Enabled {
r.GET("/metrics", metrics.Handler())
go w.startScraping()
}
go func() {
var err error

View File

@@ -1,6 +1,6 @@
<html lang="en">
<head>
<title>AdGuardHome sync</title>
<title>AdGuard Home sync</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.7.1.min.js">
</script>
{{- if .DarkMode }}
@@ -86,10 +86,13 @@
<body>
<div class="container-fluid px-4">
<div class="row">
<p class="h1">
AdGuardHome sync
<p class="h6">{{ .Version }} ({{ .Build }})</p>
</p>
<div class="d-flex align-items-center mb-3">
<img src="logo.svg" alt="Logo" class="me-3" style="height: 4em;">
<div>
<h1 class="mb-0">AdGuard Home sync</h1>
<p class="h6 text-muted mb-0">{{ .Version }} ({{ .Build }})</p>
</div>
</div>
</div>
{{- if .Metrics }}
<div class="row g-4 d-flex">

190
pkg/sync/logo.svg Normal file
View File

@@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.2"
viewBox="0 0 1000 1000"
id="svg3"
sodipodi:docname="adguardhome-sync.svg"
inkscape:version="1.4.2 (f4327f4, 2025-05-13)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs3">
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
is_visible="true"
lpeversion="1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect18"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,54.646215,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 | F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,54.646212,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="skeletal"
id="path-effect13"
is_visible="true"
lpeversion="1"
pattern="m 78.30448,0.02132 c -1.76356,0.0996 -3.48821,0.55822 -5.06836,1.34765 L 5.80252,35.08773 c -18.554321,9.281429 -18.766576,9.393634 0,18.78124 l 67.4336,33.71876 c 8.62996,4.31519 18.78393,-1.9607 18.7832,-11.60938 v -11.5 h 213 c 6.62742,0 12,-5.372583 12,-12 v -16 c 0,-6.627417 -5.37258,-12 -12,-12 h -213 v -11.5 C 92.01887,5.52137 85.74946,-0.40162 78.30448,0.02132 Z"
copytype="repeated_stretched"
prop_scale="1"
scale_y_rel="false"
spacing="100"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
hide_knot="false"
fuse_tolerance="0"
pattern-nodetypes="cccccccssssccc" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect11"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,12,0,1 @ F,0,1,1,0,12,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect33"
is_visible="true"
lpeversion="1"
nodesatellites_param=""
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<linearGradient
id="swatch26"
inkscape:swatch="solid">
<stop
style="stop-color:#000000;stop-opacity:1;"
offset="0"
id="stop26" />
</linearGradient>
<linearGradient
id="swatch25"
inkscape:swatch="solid">
<stop
style="stop-color:#407b28;stop-opacity:1;"
offset="0"
id="stop25" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 500 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="1000 : 500 : 1"
inkscape:persp3d-origin="500 : 333.33333 : 1"
id="perspective6" />
<inkscape:path-effect
effect="skeletal"
id="path-effect13-9"
is_visible="true"
lpeversion="1"
pattern="m -435.41689,700.31394 -82.73956,27.87776 82.73956,31.49534 v -23.8092 l 434.54687,9.11337 v -33.59902 l -434.54687,9.11337 z"
copytype="repeated_stretched"
prop_scale="2"
scale_y_rel="false"
spacing="100"
normal_offset="0"
tang_offset="0"
prop_units="false"
vertical_pattern="false"
hide_knot="false"
fuse_tolerance="0"
pattern-nodetypes="sccccccs" />
</defs>
<sodipodi:namedview
id="namedview3"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:zoom="0.70710678"
inkscape:cx="540.93669"
inkscape:cy="502.04582"
inkscape:window-width="1556"
inkscape:window-height="1360"
inkscape:window-x="1868"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg3" />
<path
fill="#68bc71"
d="m 993.75002,114.1 c 0,171.8 3.1,595.3 -493.8,885.9 C 3.0500233,709.4 6.2500233,285.9 6.2500233,114.1 159.35002,35.9 345.25002,0 499.95002,0 c 154.7,0 340.6,35.9 493.8,114.1 z"
id="path1"
inkscape:label="shield" />
<path
fill="#67b279"
d="M500 1000C3.1 709.4 6.2 285.9 6.2 114.1 159.4 35.9 345.3 0 500 0z"
id="path2"
inkscape:label="half-shield" />
<path
fill="#ffffff"
d="m 225,449.6 c 15,-11.7 80,-53.4 128.3,1.6 L 453.3,569.6 720,297.9 c 11.7,-10 31.7,-23.3 55,-5 L 455,716.2 Z"
id="path3"
inkscape:label="checkmark"
style="display:none" />
<circle
style="display:none;fill:#ffffff;fill-opacity:0.5;stroke:#ffffff;stroke-width:8e-08;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:100;stroke-dasharray:none;stroke-opacity:0.502604"
id="path18"
cx="-500"
cy="426"
r="400"
inkscape:label="badge"
transform="scale(-1,1)" />
<path
id="path12-8"
style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:4.00001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:100;stroke-dasharray:none;stroke-opacity:1"
d="m -75.867249,555.75073 c -1.469322,-39.92741 -12.296964,-76.43624 -30.823861,-104.61661 -21.05517,28.18037 -47.89663,45.38022 -75.18829,53.68483 l 42.51192,20.42415 c -33.35434,61.94297 -101.60764,105.3289 -167.51689,101.23666 -42.42317,-1.43193 -82.3318,-22.18867 -112.01355,-52.33871 -21.09944,-21.43232 -53.37423,-31.44115 -79.38397,-16.1329 l -10.3958,6.11853 c 43.49744,68.86447 120.54256,113.80911 201.79332,112.04834 87.97224,-4.41047 162.60077,-62.73987 194.96448,-137.74518 z M -537.90127,346.51705 c 1.46924,39.92741 12.29681,76.43626 30.82364,104.61667 21.05523,-28.18031 47.89674,-45.38011 75.18842,-53.68467 l -42.51189,-20.42423 c 33.35441,-61.94281 101.60759,-105.32857 167.51673,-101.23635 42.4233,1.43194 82.33203,22.18879 112.01381,52.33897 21.0994,21.43235 53.37417,31.44124 79.38393,16.13305 l 10.39581,-6.11852 c -43.49739,-68.86468 -120.54264,-113.8095 -201.79355,-112.04872 -87.97208,4.41046 -162.60049,62.73965 -194.96429,137.74477 z"
transform="matrix(0,-1.3167476,1.3167476,0,-94.029776,21.910887)"
inkscape:label="double-arrow"
inkscape:path-effect="#path-effect1"
inkscape:original-d="m -75.867249,555.75073 c -1.469322,-39.92741 -12.296964,-76.43624 -30.823861,-104.61661 -21.05517,28.18037 -47.89663,45.38022 -75.18829,53.68483 l 42.51192,20.42415 c -33.35434,61.94297 -101.60764,105.3289 -167.51689,101.23666 -42.42317,-1.43193 -82.3318,-22.18867 -112.01355,-52.33871 -21.09944,-21.43232 -53.37423,-31.44115 -79.38397,-16.1329 l -10.3958,6.11853 c 43.49744,68.86447 120.54256,113.80911 201.79332,112.04834 87.97224,-4.41047 162.60077,-62.73987 194.96448,-137.74518 z M -537.90127,346.51705 c 1.46924,39.92741 12.29681,76.43626 30.82364,104.61667 21.05523,-28.18031 47.89674,-45.38011 75.18842,-53.68467 l -42.51189,-20.42423 c 33.35441,-61.94281 101.60759,-105.32857 167.51673,-101.23635 42.4233,1.43194 82.33203,22.18879 112.01381,52.33897 21.0994,21.43235 53.37417,31.44124 79.38393,16.13305 l 10.39581,-6.11852 c -43.49739,-68.86468 -120.54264,-113.8095 -201.79355,-112.04872 -87.97208,4.41046 -162.60049,62.73965 -194.96429,137.74477 z" />
</svg>

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

@@ -6,6 +6,7 @@ import (
"runtime"
"sort"
"time"
"regexp"
"github.com/robfig/cron/v3"
"go.uber.org/zap"
@@ -20,7 +21,10 @@ import (
"github.com/bakito/adguardhome-sync/version"
)
var l = log.GetLogger("sync")
var (
l = log.GetLogger("sync")
fixVersionCompareRegExp = regexp.MustCompile(`[^0-9.]`)
)
// Sync config from origin to replica.
func Sync(cfg *types.Config) error {
@@ -120,6 +124,22 @@ func (w *worker) status() *syncStatus {
return syncStatus
}
func (w *worker) healthz() int {
status := w.status()
if status.Origin.Status != "success" {
return 503
}
for _, replica := range status.Replicas {
if replica.Status != "success" {
return 503
}
}
return 200
}
func (w *worker) getStatus(inst types.AdGuardInstance) replicaStatus {
st := replicaStatus{Host: inst.WebHost, URL: inst.WebURL}
@@ -293,6 +313,9 @@ func (w *worker) syncTo(l *zap.SugaredLogger, o *origin, replica types.AdGuardIn
return
}
replicaStatus.Version = fixVersionCompareRegExp.ReplaceAllString(replicaStatus.Version, "")
o.status.Version = fixVersionCompareRegExp.ReplaceAllString(o.status.Version, "")
rl.With("version", replicaStatus.Version).Info("Connected to replica")
if versions.IsNewerThan(versions.MinAgh, replicaStatus.Version) {

View File

@@ -153,7 +153,12 @@ filtering:
blocking_mode: default
parental_block_host: family-block.dns.adguard.com
safebrowsing_block_host: standard-block.dns.adguard.com
rewrites: []
rewrites:
- domain: foo.com
answer: 1.2.3.4
- domain: bar.com
answer: 1.2.3.3
safebrowsing_cache_size: 1048576
safesearch_cache_size: 1048576
parental_cache_size: 1048576

View File

@@ -2,6 +2,7 @@ replica:
versions:
- v0.107.40
- v0.107.43
- v0.107.63
- latest
mode: env