Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a38df1b59 | ||
|
|
9ec5c0412e | ||
|
|
01676e12f3 | ||
|
|
78f7d08398 | ||
|
|
11d4d14f4d | ||
|
|
ff91f4873a | ||
|
|
778bf7b516 | ||
|
|
cce24c1223 | ||
|
|
b4fabf687b | ||
|
|
74ae6a9096 | ||
|
|
92129ab069 | ||
|
|
d7f50086c3 | ||
|
|
50f883337a | ||
|
|
5a35f7c9d1 | ||
|
|
1b1a712a65 | ||
|
|
724a20e47e | ||
|
|
64c922a1d8 | ||
|
|
905c783ca9 | ||
|
|
4eac62e6ce | ||
|
|
418409ac47 | ||
|
|
4895bfdc55 | ||
|
|
976902f861 | ||
|
|
b06a1cfec0 | ||
|
|
449fce9d6a | ||
|
|
6b45caadfb | ||
|
|
06b49cb810 | ||
|
|
ae58133a0d | ||
|
|
2b0bfb126e | ||
|
|
97841e3f32 | ||
|
|
2fc2baf6f8 |
8
.github/workflows/go.yml
vendored
8
.github/workflows/go.yml
vendored
@@ -27,7 +27,11 @@ jobs:
|
||||
|
||||
test:
|
||||
name: test
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
@@ -45,7 +49,9 @@ jobs:
|
||||
run: make test-ci
|
||||
|
||||
- name: Send coverage
|
||||
if: runner.os == 'Linux'
|
||||
uses: shogo82148/actions-goveralls@v1
|
||||
continue-on-error: true
|
||||
with:
|
||||
path-to-profile: coverage.out
|
||||
|
||||
|
||||
@@ -162,6 +162,8 @@ linters:
|
||||
disabled: true
|
||||
- name: unused-receiver
|
||||
disabled: true
|
||||
- name: var-naming
|
||||
disabled: true
|
||||
staticcheck:
|
||||
checks:
|
||||
- 'all'
|
||||
|
||||
30
.toolbox.mk
30
.toolbox.mk
@@ -6,10 +6,10 @@ TB_LOCALDIR ?= $(shell which cygpath > /dev/null 2>&1 && cygpath -m $$(pwd) || p
|
||||
## Location to install dependencies to
|
||||
TB_LOCALBIN ?= $(TB_LOCALDIR)/bin
|
||||
$(TB_LOCALBIN):
|
||||
mkdir -p $(TB_LOCALBIN)
|
||||
if [ ! -e $(TB_LOCALBIN) ]; then mkdir -p $(TB_LOCALBIN); fi
|
||||
|
||||
## Tool Binaries
|
||||
TB_DEEPCOPY_GEN ?= $(TB_LOCALBIN)/deepcopy-gen
|
||||
TB_CONTROLLER_GEN ?= $(TB_LOCALBIN)/controller-gen
|
||||
TB_GINKGO ?= $(TB_LOCALBIN)/ginkgo
|
||||
TB_GOFUMPT ?= $(TB_LOCALBIN)/gofumpt
|
||||
TB_GOLANGCI_LINT ?= $(TB_LOCALBIN)/golangci-lint
|
||||
@@ -20,28 +20,28 @@ TB_OAPI_CODEGEN ?= $(TB_LOCALBIN)/oapi-codegen
|
||||
TB_SEMVER ?= $(TB_LOCALBIN)/semver
|
||||
|
||||
## Tool Versions
|
||||
# renovate: packageName=k8s.io/code-generator/cmd/deepcopy-gen
|
||||
TB_DEEPCOPY_GEN_VERSION ?= v0.33.0
|
||||
# renovate: packageName=sigs.k8s.io/controller-tools/cmd/controller-gen
|
||||
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/cmd/golangci-lint
|
||||
TB_GOLANGCI_LINT_VERSION ?= v2.1.2
|
||||
# renovate: packageName=github.com/golangci/golangci-lint/v2
|
||||
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.8.2
|
||||
TB_GORELEASER_VERSION ?= v2.11.0
|
||||
# renovate: packageName=go.uber.org/mock/mockgen
|
||||
TB_MOCKGEN_VERSION ?= v0.5.1
|
||||
# renovate: packageName=github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen
|
||||
TB_MOCKGEN_VERSION ?= v0.5.2
|
||||
# renovate: packageName=github.com/oapi-codegen/oapi-codegen/v2
|
||||
TB_OAPI_CODEGEN_VERSION ?= v2.4.1
|
||||
# renovate: packageName=github.com/bakito/semver
|
||||
TB_SEMVER_VERSION ?= v1.1.3
|
||||
|
||||
## Tool Installer
|
||||
.PHONY: tb.deepcopy-gen
|
||||
tb.deepcopy-gen: $(TB_DEEPCOPY_GEN) ## Download deepcopy-gen locally if necessary.
|
||||
$(TB_DEEPCOPY_GEN): $(TB_LOCALBIN)
|
||||
test -s $(TB_LOCALBIN)/deepcopy-gen || GOBIN=$(TB_LOCALBIN) go install k8s.io/code-generator/cmd/deepcopy-gen@$(TB_DEEPCOPY_GEN_VERSION)
|
||||
.PHONY: tb.controller-gen
|
||||
tb.controller-gen: $(TB_CONTROLLER_GEN) ## Download controller-gen locally if necessary.
|
||||
$(TB_CONTROLLER_GEN): $(TB_LOCALBIN)
|
||||
test -s $(TB_LOCALBIN)/controller-gen || GOBIN=$(TB_LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(TB_CONTROLLER_GEN_VERSION)
|
||||
.PHONY: tb.ginkgo
|
||||
tb.ginkgo: $(TB_GINKGO) ## Download ginkgo locally if necessary.
|
||||
$(TB_GINKGO): $(TB_LOCALBIN)
|
||||
@@ -79,7 +79,7 @@ $(TB_SEMVER): $(TB_LOCALBIN)
|
||||
.PHONY: tb.reset
|
||||
tb.reset:
|
||||
@rm -f \
|
||||
$(TB_LOCALBIN)/deepcopy-gen \
|
||||
$(TB_LOCALBIN)/controller-gen \
|
||||
$(TB_LOCALBIN)/ginkgo \
|
||||
$(TB_LOCALBIN)/gofumpt \
|
||||
$(TB_LOCALBIN)/golangci-lint \
|
||||
@@ -93,7 +93,7 @@ tb.reset:
|
||||
.PHONY: tb.update
|
||||
tb.update: tb.reset
|
||||
toolbox makefile --renovate -f $(TB_LOCALDIR)/Makefile \
|
||||
k8s.io/code-generator/cmd/deepcopy-gen@github.com/kubernetes/code-generator \
|
||||
sigs.k8s.io/controller-tools/cmd/controller-gen@github.com/kubernetes-sigs/controller-tools \
|
||||
mvdan.cc/gofumpt@github.com/mvdan/gofumpt \
|
||||
github.com/golangci/golangci-lint/v2/cmd/golangci-lint \
|
||||
github.com/segmentio/golines \
|
||||
|
||||
7
Makefile
7
Makefile
@@ -9,10 +9,11 @@ lint: tb.golangci-lint
|
||||
tidy:
|
||||
go mod tidy
|
||||
|
||||
generate: tb.deepcopy-gen
|
||||
generate: model mocks deepcopy-gen
|
||||
deepcopy-gen: tb.controller-gen
|
||||
@mkdir -p ./tmp
|
||||
@touch ./tmp/deepcopy-gen-boilerplate.go.txt
|
||||
$(TB_DEEPCOPY_GEN) --go-header-file ./tmp/deepcopy-gen-boilerplate.go.txt --bounding-dirs ./pkg/types
|
||||
$(TB_CONTROLLER_GEN) paths=./pkg/types object
|
||||
|
||||
fmt: tb.golines tb.gofumpt
|
||||
$(TB_GOLINES) --base-formatter="$(TB_GOFUMPT)" --max-len=120 --write-output .
|
||||
@@ -73,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
|
||||
|
||||
24
README.md
24
README.md
@@ -3,7 +3,9 @@
|
||||
[](https://goreportcard.com/report/github.com/bakito/adguardhome-sync)
|
||||
[](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
|
||||
|
||||
@@ -193,6 +195,7 @@ For Replicas replace `#` with the index number for the replica. E.g: `REPLICA#_U
|
||||
| ORIGIN_USERNAME (string) | string | Adguardhome username |
|
||||
| ORIGIN_PASSWORD (string) | string | Adguardhome password |
|
||||
| ORIGIN_COOKIE (string) | string | Adguardhome cookie |
|
||||
| ORIGIN_REQUEST_HEADERS (map) | map | Request Headers 'key1:value1,key2:value2' |
|
||||
| ORIGIN_INSECURE_SKIP_VERIFY (bool) | bool | Skip TLS verification |
|
||||
| ORIGIN_AUTO_SETUP (bool) | bool | Automatically setup the instance if it is not initialized |
|
||||
| ORIGIN_INTERFACE_NAME (string) | string | Network interface name |
|
||||
@@ -203,6 +206,7 @@ For Replicas replace `#` with the index number for the replica. E.g: `REPLICA#_U
|
||||
| REPLICA#_USERNAME (string) | string | Adguardhome username |
|
||||
| REPLICA#_PASSWORD (string) | string | Adguardhome password |
|
||||
| REPLICA#_COOKIE (string) | string | Adguardhome cookie |
|
||||
| REPLICA#_REQUEST_HEADERS (map) | map | Request Headers 'key1:value1,key2:value2' |
|
||||
| REPLICA#_INSECURE_SKIP_VERIFY (bool) | bool | Skip TLS verification |
|
||||
| REPLICA#_AUTO_SETUP (bool) | bool | Automatically setup the instance if it is not initialized |
|
||||
| REPLICA#_INTERFACE_NAME (string) | string | Network interface name |
|
||||
@@ -264,6 +268,8 @@ origin:
|
||||
username: username
|
||||
password: password
|
||||
# cookie: Origin-Cookie-Name=CCCOOOKKKIIIEEE
|
||||
# requestHeaders: # Additional request headers
|
||||
# AAA: bbb
|
||||
|
||||
# replicas instances
|
||||
replicas:
|
||||
@@ -278,6 +284,8 @@ replicas:
|
||||
# cookie: Replica2-Cookie-Name=CCCOOOKKKIIIEEE
|
||||
# autoSetup: true # if true, AdGuardHome is automatically initialized.
|
||||
# webURL: "https://some-other.url" # used in the web interface (default: <replica-url>
|
||||
# requestHeaders: # Additional request headers
|
||||
# AAA: bbb
|
||||
|
||||
# Configure the sync API server, disabled if api port is 0
|
||||
api:
|
||||
@@ -320,9 +328,12 @@ features:
|
||||
accessLists: true
|
||||
rewrites: true
|
||||
```
|
||||
|
||||
## Home Assistant AdGuard Home Add-on users
|
||||
|
||||
To enable syncing with a Home Assistant instance using the [AdGuard Home Add-on](https://github.com/hassio-addons/addon-adguard-home), you will need to enable the disabled ports, under the Network heading
|
||||
To enable syncing with a Home Assistant instance using
|
||||
the [AdGuard Home Add-on](https://github.com/hassio-addons/addon-adguard-home), you will need to enable the disabled
|
||||
ports, under the Network heading
|
||||
|
||||

|
||||
|
||||
@@ -334,9 +345,12 @@ Don't forget to save and restart the add-on.
|
||||
|
||||
Depending on your setup, you may also need to disable SSL for the add-on.
|
||||
|
||||
The username:password required for the Home Assistant replica is the one you use to login to your instance, however it's recommended to setup a new local only user with minimal permissions.
|
||||
The username:password required for the Home Assistant replica is the one you use to login to your instance, however it's
|
||||
recommended to setup a new local only user with minimal permissions.
|
||||
|
||||
All credit for this method goes to [Brunty](https://github.com/brunty) who has a far more [detailed write up](https://brunty.me/post/replicate-adguard-home-settings-into-home-assistant-adguard-home-addon/) about this on his blog.
|
||||
All credit for this method goes to [Brunty](https://github.com/brunty) who has a far
|
||||
more [detailed write up](https://brunty.me/post/replicate-adguard-home-settings-into-home-assistant-adguard-home-addon/)
|
||||
about this on his blog.
|
||||
|
||||
## Log Level
|
||||
|
||||
|
||||
@@ -30,9 +30,14 @@ func printEnvTags(t reflect.Type, prefix string) {
|
||||
}
|
||||
|
||||
envTag := field.Tag.Get("env")
|
||||
if envTag == "REPLICA" {
|
||||
if envTag == "" {
|
||||
switch field.Name {
|
||||
case "Origin":
|
||||
envTag = "ORIGIN"
|
||||
case "Replica":
|
||||
envTag = "REPLICA#"
|
||||
}
|
||||
}
|
||||
combinedTag := envTag
|
||||
if prefix != "" && envTag != "" {
|
||||
combinedTag = prefix + "_" + envTag
|
||||
|
||||
18
go.mod
18
go.mod
@@ -1,11 +1,11 @@
|
||||
module github.com/bakito/adguardhome-sync
|
||||
|
||||
go 1.24.1
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/caarlos0/env/v11 v11.3.1
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/go-faker/faker/v4 v4.6.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
|
||||
github.com/jinzhu/copier v0.4.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.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.0
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e
|
||||
k8s.io/apimachinery v0.33.2
|
||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -42,7 +42,7 @@ require (
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416 // indirect
|
||||
github.com/google/pprof v0.0.0-20250501235452-c0086092b71a // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
|
||||
32
go.sum
32
go.sum
@@ -28,10 +28,10 @@ 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/go-faker/faker/v4 v4.6.0 h1:6aOPzNptRiDwD14HuAnEtlTa+D1IfFuEHO8+vEFwjTs=
|
||||
github.com/go-faker/faker/v4 v4.6.0/go.mod h1:ZmrHuVtTTm2Em9e0Du6CJ9CADaLEzGXW62z1YqFH0m0=
|
||||
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=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
@@ -54,8 +54,8 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416 h1:1/qwHx8P72glDXdyCKesJ+/c40x71SY4q2avOxJ2iYQ=
|
||||
github.com/google/pprof v0.0.0-20250422154841-e1f9c1950416/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
||||
github.com/google/pprof v0.0.0-20250501235452-c0086092b71a h1:rDA3FfmxwXR+BVKKdz55WwMJ1pD2hJQNW31d+l3mPk4=
|
||||
github.com/google/pprof v0.0.0-20250501235452-c0086092b71a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA=
|
||||
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/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
@@ -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=
|
||||
@@ -144,8 +144,8 @@ go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/mock v0.5.1 h1:ASgazW/qBmR+A32MYFDB6E2POoTgOwT509VP0CT/fjs=
|
||||
go.uber.org/mock v0.5.1/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
@@ -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.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||
k8s.io/apimachinery v0.33.0/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-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro=
|
||||
k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/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
190
media/adguardhome-sync.svg
Normal 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 |
@@ -52,7 +52,7 @@ func New(config types.AdGuardInstance) (Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
u.Path = path.Clean(u.Path)
|
||||
cl := resty.New().SetBaseURL(u.String()).SetDisableWarn(true)
|
||||
cl := resty.New().SetBaseURL(u.String()).SetDisableWarn(true).SetHeaders(config.RequestHeaders)
|
||||
|
||||
// #nosec G402 has to be explicitly enabled
|
||||
cl.SetTLSClientConfig(&tls.Config{InsecureSkipVerify: config.InsecureSkipVerify})
|
||||
|
||||
@@ -1199,7 +1199,13 @@ type ClientsFindParams struct {
|
||||
// FilteringCheckHostParams defines parameters for FilteringCheckHost.
|
||||
type FilteringCheckHostParams struct {
|
||||
// Name Filter by host name
|
||||
Name *string `form:"name,omitempty" json:"name,omitempty"`
|
||||
Name string `form:"name" json:"name"`
|
||||
|
||||
// Client Optional ClientID or client IP address
|
||||
Client *string `form:"client,omitempty" json:"client,omitempty"`
|
||||
|
||||
// Qtype Optional DNS type
|
||||
Qtype *string `form:"qtype,omitempty" json:"qtype,omitempty"`
|
||||
}
|
||||
|
||||
// QueryLogParams defines parameters for QueryLog.
|
||||
@@ -4256,9 +4262,37 @@ func NewFilteringCheckHostRequest(server string, params *FilteringCheckHostParam
|
||||
if params != nil {
|
||||
queryValues := queryURL.Query()
|
||||
|
||||
if params.Name != nil {
|
||||
if queryFrag, err := runtime.StyleParamWithLocation("form", true, "name", runtime.ParamLocationQuery, params.Name); err != nil {
|
||||
return nil, err
|
||||
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
for k, v := range parsed {
|
||||
for _, v2 := range v {
|
||||
queryValues.Add(k, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if queryFrag, err := runtime.StyleParamWithLocation("form", true, "name", runtime.ParamLocationQuery, *params.Name); err != nil {
|
||||
if params.Client != nil {
|
||||
|
||||
if queryFrag, err := runtime.StyleParamWithLocation("form", true, "client", runtime.ParamLocationQuery, *params.Client); err != nil {
|
||||
return nil, err
|
||||
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
for k, v := range parsed {
|
||||
for _, v2 := range v {
|
||||
queryValues.Add(k, v2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if params.Qtype != nil {
|
||||
|
||||
if queryFrag, err := runtime.StyleParamWithLocation("form", true, "qtype", runtime.ParamLocationQuery, *params.Qtype); err != nil {
|
||||
return nil, err
|
||||
} else if parsed, err := url.ParseQuery(queryFrag); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
"webURL": {
|
||||
"format": "uri",
|
||||
"type": "string"
|
||||
},
|
||||
"requestHeaders": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
|
||||
@@ -63,18 +63,27 @@ func Get(configFile string, flags Flags) (*AppConfig, error) {
|
||||
replicaDhcpServer := cfg.Replica.DHCPServerEnabled
|
||||
cfg.Replica.DHCPServerEnabled = nil
|
||||
|
||||
// ignore replicas form env parsing as they are handled separately
|
||||
// ignore origin and replicas form env parsing as they are handled separately
|
||||
replicas := cfg.Replicas
|
||||
cfg.Replicas = nil
|
||||
replica := cfg.Replica
|
||||
cfg.Replica = nil
|
||||
origin := cfg.Origin
|
||||
cfg.Origin = nil
|
||||
|
||||
// overwrite from env vars
|
||||
if err := env.Parse(cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := env.ParseWithOptions(cfg.Replica, env.Options{Prefix: "REPLICA_"}); err != nil {
|
||||
if err := env.ParseWithOptions(origin, env.Options{Prefix: "ORIGIN_"}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// restore the replica
|
||||
if err := env.ParseWithOptions(replica, env.Options{Prefix: "REPLICA_"}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// restore origin and replica
|
||||
cfg.Origin = origin
|
||||
cfg.Replica = replica
|
||||
cfg.Replicas = replicas
|
||||
|
||||
// if not set from env, use previous value
|
||||
@@ -82,10 +91,6 @@ func Get(configFile string, flags Flags) (*AppConfig, error) {
|
||||
cfg.Replica.DHCPServerEnabled = replicaDhcpServer
|
||||
}
|
||||
|
||||
if err := env.ParseWithOptions(&cfg.Origin, env.Options{Prefix: "ORIGIN_"}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if cfg.Replica != nil &&
|
||||
cfg.Replica.URL == "" &&
|
||||
cfg.Replica.Username == "" {
|
||||
@@ -112,7 +117,7 @@ func Get(configFile string, flags Flags) (*AppConfig, error) {
|
||||
func initialConfig() *types.Config {
|
||||
return &types.Config{
|
||||
RunOnStart: true,
|
||||
Origin: types.AdGuardInstance{
|
||||
Origin: &types.AdGuardInstance{
|
||||
APIPath: "/control",
|
||||
},
|
||||
Replica: &types.AdGuardInstance{
|
||||
|
||||
@@ -5,9 +5,11 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/format"
|
||||
)
|
||||
|
||||
func TestCmd(t *testing.T) {
|
||||
format.TruncatedDiff = false
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Config Suite")
|
||||
}
|
||||
|
||||
@@ -44,6 +44,18 @@ var _ = Describe("Config", func() {
|
||||
Ω(err.Error()).Should(ContainSubstring("mixed replica config in use"))
|
||||
})
|
||||
})
|
||||
Context("Env Var Clash", func() {
|
||||
It("should not use USERNAME env variable if it is defined (#570)", func() {
|
||||
incorrect := "ThisIsNotTheCorrectUsername"
|
||||
setEnv("USERNAME", incorrect)
|
||||
flags.EXPECT().Changed(gm.Any()).Return(false).AnyTimes()
|
||||
|
||||
c, err := config.Get("../../testdata/config_test_replica.yaml", flags)
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(c.Get().Origin.Username).ShouldNot(Equal(incorrect))
|
||||
Ω(c.Get().Replicas[0].Username).ShouldNot(Equal(incorrect))
|
||||
})
|
||||
})
|
||||
Context("Origin Url", func() {
|
||||
It("should have the origin URL from the config file", func() {
|
||||
flags.EXPECT().Changed(gm.Any()).Return(false).AnyTimes()
|
||||
@@ -232,6 +244,27 @@ var _ = Describe("Config", func() {
|
||||
Ω(cfg.Get().Features.DNS.ServerConfig).Should(BeFalse())
|
||||
})
|
||||
})
|
||||
|
||||
Context("Headers", func() {
|
||||
It("have headers from the config file", func() {
|
||||
flags.EXPECT().Changed(gm.Any()).Return(false).AnyTimes()
|
||||
|
||||
cfg, err := config.Get("../../testdata/config_test_replicas.yaml", flags)
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(cfg.Get().Replicas[0].RequestHeaders).Should(HaveLen(2))
|
||||
Ω(cfg.Get().Replicas[0].RequestHeaders["FOO"]).Should(Equal("bar"))
|
||||
Ω(cfg.Get().Replicas[0].RequestHeaders["Client-ID"]).Should(Equal("xxxx"))
|
||||
})
|
||||
It("have headers from the config file will be replaced when defined as ENV", func() {
|
||||
setEnv("REPLICA1_REQUEST_HEADERS", "AAA:bbb")
|
||||
flags.EXPECT().Changed(gm.Any()).Return(false).AnyTimes()
|
||||
|
||||
cfg, err := config.Get("../../testdata/config_test_replicas.yaml", flags)
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(cfg.Get().Replicas[0].RequestHeaders).Should(HaveLen(1))
|
||||
Ω(cfg.Get().Replicas[0].RequestHeaders["AAA"]).Should(Equal("bbb"))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -19,7 +19,8 @@ var _ = Describe("Config", func() {
|
||||
Ω(result).Should(Equal(path))
|
||||
})
|
||||
It("should the file in HOME dir", func() {
|
||||
home := os.Getenv("HOME")
|
||||
home, err := os.UserHomeDir()
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
result, err := configFilePath("")
|
||||
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
|
||||
@@ -19,6 +19,7 @@ var _ = Describe("Config", func() {
|
||||
)
|
||||
BeforeEach(func() {
|
||||
cfg = &types.Config{
|
||||
Origin: &types.AdGuardInstance{},
|
||||
Replica: &types.AdGuardInstance{},
|
||||
Features: types.Features{
|
||||
DNS: types.DNS{
|
||||
@@ -143,7 +144,7 @@ var _ = Describe("Config", func() {
|
||||
})
|
||||
Context("readOriginFlags", func() {
|
||||
It("should change all values", func() {
|
||||
cfg.Origin = types.AdGuardInstance{
|
||||
cfg.Origin = &types.AdGuardInstance{
|
||||
URL: "1",
|
||||
WebURL: "2",
|
||||
APIPath: "3",
|
||||
@@ -172,7 +173,7 @@ var _ = Describe("Config", func() {
|
||||
err := readFlags(cfg, flags)
|
||||
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(cfg.Origin).Should(Equal(types.AdGuardInstance{
|
||||
Ω(cfg.Origin).Should(Equal(&types.AdGuardInstance{
|
||||
URL: "a",
|
||||
WebURL: "b",
|
||||
APIPath: "c",
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
var printConfigTemplate string
|
||||
|
||||
func (ac *AppConfig) Print() error {
|
||||
originVersion := aghVersion(ac.cfg.Origin)
|
||||
originVersion := aghVersion(*ac.cfg.Origin)
|
||||
var replicaVersions []string
|
||||
for _, replica := range ac.cfg.Replicas {
|
||||
replicaVersions = append(replicaVersions, aghVersion(replica))
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/bakito/adguardhome-sync/pkg/test/matchers"
|
||||
"github.com/bakito/adguardhome-sync/pkg/types"
|
||||
"github.com/bakito/adguardhome-sync/version"
|
||||
)
|
||||
@@ -22,7 +23,7 @@ var _ = Describe("AppConfig", func() {
|
||||
BeforeEach(func() {
|
||||
ac = &AppConfig{
|
||||
cfg: &types.Config{
|
||||
Origin: types.AdGuardInstance{
|
||||
Origin: &types.AdGuardInstance{
|
||||
URL: "https://ha.xxxx.net:3000",
|
||||
},
|
||||
},
|
||||
@@ -37,17 +38,15 @@ origin:
|
||||
It("should printInternal config without file", func() {
|
||||
out, err := ac.printInternal(env, "v0.0.1", []string{"v0.0.2"})
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(
|
||||
out,
|
||||
).Should(Equal(fmt.Sprintf(expected(1), version.Version, version.Build, runtime.GOOS, runtime.GOARCH)))
|
||||
Ω(out).
|
||||
Should(matchers.EqualIgnoringLineEndings(fmt.Sprintf(expected(1), version.Version, version.Build, runtime.GOOS, runtime.GOARCH)))
|
||||
})
|
||||
It("should printInternal config with file", func() {
|
||||
ac.filePath = "config.yaml"
|
||||
out, err := ac.printInternal(env, "v0.0.1", []string{"v0.0.2"})
|
||||
Ω(err).ShouldNot(HaveOccurred())
|
||||
Ω(
|
||||
out,
|
||||
).Should(Equal(fmt.Sprintf(expected(2), version.Version, version.Build, runtime.GOOS, runtime.GOARCH)))
|
||||
Ω(out).
|
||||
Should(matchers.EqualIgnoringLineEndings(fmt.Sprintf(expected(2), version.Version, version.Build, runtime.GOOS, runtime.GOARCH)))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -539,10 +539,10 @@ func (mr *MockClientMockRecorder) Stats() *gomock.Call {
|
||||
}
|
||||
|
||||
// StatsConfig mocks base method.
|
||||
func (m *MockClient) StatsConfig() (*model.PutStatsConfigUpdateRequest, error) {
|
||||
func (m *MockClient) StatsConfig() (*model.GetStatsConfigResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "StatsConfig")
|
||||
ret0, _ := ret[0].(*model.PutStatsConfigUpdateRequest)
|
||||
ret0, _ := ret[0].(*model.GetStatsConfigResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -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
|
||||
|
||||
@@ -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
190
pkg/sync/logo.svg
Normal 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 |
@@ -28,7 +28,7 @@ func (w *worker) startScraping() {
|
||||
func (w *worker) scrape() {
|
||||
var iml metrics.InstanceMetricsList
|
||||
|
||||
iml.Metrics = append(iml.Metrics, w.getMetrics(w.cfg.Origin))
|
||||
iml.Metrics = append(iml.Metrics, w.getMetrics(*w.cfg.Origin))
|
||||
for _, replica := range w.cfg.Replicas {
|
||||
iml.Metrics = append(iml.Metrics, w.getMetrics(replica))
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -100,7 +104,7 @@ type worker struct {
|
||||
|
||||
func (w *worker) status() *syncStatus {
|
||||
syncStatus := &syncStatus{
|
||||
Origin: w.getStatus(w.cfg.Origin),
|
||||
Origin: w.getStatus(*w.cfg.Origin),
|
||||
}
|
||||
|
||||
for _, replica := range w.cfg.Replicas {
|
||||
@@ -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}
|
||||
|
||||
@@ -158,7 +178,7 @@ func (w *worker) sync() {
|
||||
w.running = false
|
||||
}()
|
||||
|
||||
oc, err := w.createClient(w.cfg.Origin)
|
||||
oc, err := w.createClient(*w.cfg.Origin)
|
||||
if err != nil {
|
||||
l.With("error", err, "url", w.cfg.Origin.URL).Error("Error creating origin client")
|
||||
return
|
||||
@@ -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) {
|
||||
|
||||
@@ -576,7 +576,7 @@ var _ = Describe("Sync", func() {
|
||||
Context("sync", func() {
|
||||
BeforeEach(func() {
|
||||
w.cfg = &types.Config{
|
||||
Origin: types.AdGuardInstance{},
|
||||
Origin: &types.AdGuardInstance{},
|
||||
Replica: &types.AdGuardInstance{URL: "foo"},
|
||||
Features: types.Features{
|
||||
DHCP: types.DHCP{
|
||||
|
||||
44
pkg/test/matchers/matchers.go
Normal file
44
pkg/test/matchers/matchers.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/onsi/gomega/format"
|
||||
"github.com/onsi/gomega/types"
|
||||
)
|
||||
|
||||
type equalIgnoringLineEndingsMatcher struct {
|
||||
expected string
|
||||
}
|
||||
|
||||
func (matcher *equalIgnoringLineEndingsMatcher) Match(actual any) (success bool, err error) {
|
||||
actualStr, ok := actual.(string)
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
normalizedActual := strings.ReplaceAll(actualStr, "\r\n", "\n")
|
||||
normalizedExpected := strings.ReplaceAll(matcher.expected, "\r\n", "\n")
|
||||
|
||||
return normalizedActual == normalizedExpected, nil
|
||||
}
|
||||
|
||||
func (matcher *equalIgnoringLineEndingsMatcher) FailureMessage(actual any) (message string) {
|
||||
actualString, actualOK := actual.(string)
|
||||
if actualOK {
|
||||
return format.MessageWithDiff(actualString, "to equal", matcher.expected)
|
||||
}
|
||||
|
||||
return format.Message(actual, "to equal", matcher.expected)
|
||||
}
|
||||
|
||||
func (matcher *equalIgnoringLineEndingsMatcher) NegatedFailureMessage(actual any) (message string) {
|
||||
return format.Message(actual, "not to equal", matcher.expected)
|
||||
}
|
||||
|
||||
// EqualIgnoringLineEndings returns a new matcher.
|
||||
func EqualIgnoringLineEndings(expected string) types.GomegaMatcher {
|
||||
return &equalIgnoringLineEndingsMatcher{
|
||||
expected: expected,
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
//go:build !ignore_autogenerated
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package types
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AdGuardInstance) DeepCopyInto(out *AdGuardInstance) {
|
||||
*out = *in
|
||||
if in.DHCPServerEnabled != nil {
|
||||
in, out := &in.DHCPServerEnabled, &out.DHCPServerEnabled
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdGuardInstance.
|
||||
func (in *AdGuardInstance) DeepCopy() *AdGuardInstance {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AdGuardInstance)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Config) DeepCopyInto(out *Config) {
|
||||
*out = *in
|
||||
in.Origin.DeepCopyInto(&out.Origin)
|
||||
if in.Replica != nil {
|
||||
in, out := &in.Replica, &out.Replica
|
||||
*out = new(AdGuardInstance)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Replicas != nil {
|
||||
in, out := &in.Replicas, &out.Replicas
|
||||
*out = make([]AdGuardInstance, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
out.API = in.API
|
||||
out.Features = in.Features
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config.
|
||||
func (in *Config) DeepCopy() *Config {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Config)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
// Package types
|
||||
// +kubebuilder:object:generate=true
|
||||
package types
|
||||
|
||||
import (
|
||||
@@ -19,17 +21,17 @@ const (
|
||||
// +k8s:deepcopy-gen=true
|
||||
type Config struct {
|
||||
// Origin adguardhome instance
|
||||
Origin AdGuardInstance `env:"ORIGIN" json:"origin" yaml:"origin"`
|
||||
Origin *AdGuardInstance `json:"origin" yaml:"origin"`
|
||||
// One single replica adguardhome instance
|
||||
Replica *AdGuardInstance `env:"REPLICA" json:"replica,omitempty" yaml:"replica,omitempty"`
|
||||
Replica *AdGuardInstance `json:"replica,omitempty" yaml:"replica,omitempty"`
|
||||
// Multiple replica instances
|
||||
Replicas []AdGuardInstance ` json:"replicas,omitempty" yaml:"replicas,omitempty" faker:"slice_len=2"`
|
||||
Cron string `env:"CRON" json:"cron,omitempty" yaml:"cron,omitempty" documentation:"Cron expression for the sync interval"`
|
||||
RunOnStart bool `env:"RUN_ON_START" json:"runOnStart,omitempty" yaml:"runOnStart,omitempty" documentation:"Run the sung on startup"`
|
||||
PrintConfigOnly bool `env:"PRINT_CONFIG_ONLY" json:"printConfigOnly,omitempty" yaml:"printConfigOnly,omitempty" documentation:"Print current config only and stop the application"`
|
||||
ContinueOnError bool `env:"CONTINUE_ON_ERROR" json:"continueOnError,omitempty" yaml:"continueOnError,omitempty" documentation:"Continue sync on errors"`
|
||||
API API ` json:"api,omitempty" yaml:"api,omitempty"`
|
||||
Features Features ` json:"features,omitempty" yaml:"features,omitempty"`
|
||||
Replicas []AdGuardInstance `json:"replicas,omitempty" yaml:"replicas,omitempty" faker:"slice_len=2"`
|
||||
Cron string `json:"cron,omitempty" yaml:"cron,omitempty" documentation:"Cron expression for the sync interval" env:"CRON"`
|
||||
RunOnStart bool `json:"runOnStart,omitempty" yaml:"runOnStart,omitempty" documentation:"Run the sung on startup" env:"RUN_ON_START"`
|
||||
PrintConfigOnly bool `json:"printConfigOnly,omitempty" yaml:"printConfigOnly,omitempty" documentation:"Print current config only and stop the application" env:"PRINT_CONFIG_ONLY"`
|
||||
ContinueOnError bool `json:"continueOnError,omitempty" yaml:"continueOnError,omitempty" documentation:"Continue sync on errors" env:"CONTINUE_ON_ERROR"`
|
||||
API API `json:"api,omitempty" yaml:"api,omitempty"`
|
||||
Features Features `json:"features,omitempty" yaml:"features,omitempty"`
|
||||
}
|
||||
|
||||
// API configuration.
|
||||
@@ -149,6 +151,7 @@ type AdGuardInstance struct {
|
||||
Username string `documentation:"Adguardhome username" env:"USERNAME" json:"username,omitempty" yaml:"username,omitempty"`
|
||||
Password string `documentation:"Adguardhome password" env:"PASSWORD" json:"password,omitempty" yaml:"password,omitempty"`
|
||||
Cookie string `documentation:"Adguardhome cookie" env:"COOKIE" json:"cookie,omitempty" yaml:"cookie,omitempty"`
|
||||
RequestHeaders map[string]string `documentation:"Request Headers 'key1:value1,key2:value2'" env:"REQUEST_HEADERS" json:"requestHeaders,omitempty" yaml:"requestHeaders,omitempty"`
|
||||
InsecureSkipVerify bool `documentation:"Skip TLS verification" env:"INSECURE_SKIP_VERIFY" json:"insecureSkipVerify" yaml:"insecureSkipVerify"`
|
||||
AutoSetup bool `documentation:"Automatically setup the instance if it is not initialized" env:"AUTO_SETUP" json:"autoSetup" yaml:"autoSetup"`
|
||||
InterfaceName string `documentation:"Network interface name" env:"INTERFACE_NAME" json:"interfaceName,omitempty" yaml:"interfaceName,omitempty"`
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
@@ -39,6 +41,7 @@ var _ = Describe("Types", func() {
|
||||
Context("Config", func() {
|
||||
Context("init", func() {
|
||||
cfg := Config{
|
||||
Origin: &AdGuardInstance{},
|
||||
Replicas: []AdGuardInstance{
|
||||
{URL: "https://localhost:3000"},
|
||||
},
|
||||
@@ -53,6 +56,7 @@ var _ = Describe("Types", func() {
|
||||
Context("UniqueReplicas", func() {
|
||||
It("should return unique replicas in the array", func() {
|
||||
cfg := Config{
|
||||
Origin: &AdGuardInstance{},
|
||||
Replicas: []AdGuardInstance{
|
||||
{URL: "a"},
|
||||
{URL: "a", APIPath: DefaultAPIPath},
|
||||
@@ -68,6 +72,7 @@ var _ = Describe("Types", func() {
|
||||
Context("mask", func() {
|
||||
It("should mask all names and passwords", func() {
|
||||
cfg := Config{
|
||||
Origin: &AdGuardInstance{},
|
||||
Replicas: []AdGuardInstance{
|
||||
{URL: "a", Username: "user", Password: "pass"},
|
||||
},
|
||||
@@ -124,6 +129,8 @@ var _ = Describe("Types", func() {
|
||||
Context("Certs", func() {
|
||||
It("should use default crt and key", func() {
|
||||
crt, key := t.Certs()
|
||||
crt = normalizePath(crt)
|
||||
key = normalizePath(key)
|
||||
Ω(crt).Should(Equal("/path/to/certs/tls.crt"))
|
||||
Ω(key).Should(Equal("/path/to/certs/tls.key"))
|
||||
})
|
||||
@@ -131,9 +138,15 @@ var _ = Describe("Types", func() {
|
||||
t.CertName = "foo.crt"
|
||||
t.KeyName = "bar.key"
|
||||
crt, key := t.Certs()
|
||||
crt = normalizePath(crt)
|
||||
key = normalizePath(key)
|
||||
Ω(crt).Should(Equal("/path/to/certs/foo.crt"))
|
||||
Ω(key).Should(Equal("/path/to/certs/bar.key"))
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
func normalizePath(path string) string {
|
||||
return strings.ReplaceAll(path, "\\", "/")
|
||||
}
|
||||
|
||||
209
pkg/types/zz_generated.deepcopy.go
Normal file
209
pkg/types/zz_generated.deepcopy.go
Normal file
@@ -0,0 +1,209 @@
|
||||
//go:build !ignore_autogenerated
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package types
|
||||
|
||||
import ()
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *API) DeepCopyInto(out *API) {
|
||||
*out = *in
|
||||
out.Metrics = in.Metrics
|
||||
out.TLS = in.TLS
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new API.
|
||||
func (in *API) DeepCopy() *API {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(API)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AdGuardInstance) DeepCopyInto(out *AdGuardInstance) {
|
||||
*out = *in
|
||||
if in.RequestHeaders != nil {
|
||||
in, out := &in.RequestHeaders, &out.RequestHeaders
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.DHCPServerEnabled != nil {
|
||||
in, out := &in.DHCPServerEnabled, &out.DHCPServerEnabled
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AdGuardInstance.
|
||||
func (in *AdGuardInstance) DeepCopy() *AdGuardInstance {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AdGuardInstance)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Config) DeepCopyInto(out *Config) {
|
||||
*out = *in
|
||||
if in.Origin != nil {
|
||||
in, out := &in.Origin, &out.Origin
|
||||
*out = new(AdGuardInstance)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Replica != nil {
|
||||
in, out := &in.Replica, &out.Replica
|
||||
*out = new(AdGuardInstance)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Replicas != nil {
|
||||
in, out := &in.Replicas, &out.Replicas
|
||||
*out = make([]AdGuardInstance, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
out.API = in.API
|
||||
out.Features = in.Features
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Config.
|
||||
func (in *Config) DeepCopy() *Config {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Config)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DHCP) DeepCopyInto(out *DHCP) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DHCP.
|
||||
func (in *DHCP) DeepCopy() *DHCP {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DHCP)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DNS) DeepCopyInto(out *DNS) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS.
|
||||
func (in *DNS) DeepCopy() *DNS {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DNS)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Features) DeepCopyInto(out *Features) {
|
||||
*out = *in
|
||||
out.DNS = in.DNS
|
||||
out.DHCP = in.DHCP
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Features.
|
||||
func (in *Features) DeepCopy() *Features {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Features)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *InstallConfig) DeepCopyInto(out *InstallConfig) {
|
||||
*out = *in
|
||||
out.Web = in.Web
|
||||
out.DNS = in.DNS
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallConfig.
|
||||
func (in *InstallConfig) DeepCopy() *InstallConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(InstallConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *InstallPort) DeepCopyInto(out *InstallPort) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallPort.
|
||||
func (in *InstallPort) DeepCopy() *InstallPort {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(InstallPort)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Metrics) DeepCopyInto(out *Metrics) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Metrics.
|
||||
func (in *Metrics) DeepCopy() *Metrics {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Metrics)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Protection) DeepCopyInto(out *Protection) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Protection.
|
||||
func (in *Protection) DeepCopy() *Protection {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Protection)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TLS) DeepCopyInto(out *TLS) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLS.
|
||||
func (in *TLS) DeepCopy() *TLS {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TLS)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -5,8 +5,8 @@
|
||||
"customType": "regex",
|
||||
"datasourceTemplate": "go",
|
||||
"description": "Update toolbox tools in .toolbox.mk",
|
||||
"fileMatch": [
|
||||
"^\\.toolbox\\.mk$"
|
||||
"managerFilePatterns": [
|
||||
".toolbox.mk"
|
||||
],
|
||||
"matchStrings": [
|
||||
"# renovate: packageName=(?<packageName>.+?)\\s+.+?_VERSION \\?= (?<currentValue>.+?)\\s"
|
||||
@@ -16,8 +16,8 @@
|
||||
"customType": "regex",
|
||||
"datasourceTemplate": "github-releases",
|
||||
"description": "Update github _VERSION Makefile",
|
||||
"fileMatch": [
|
||||
"^Makefile$"
|
||||
"managerFilePatterns": [
|
||||
"Makefile"
|
||||
],
|
||||
"matchStrings": [
|
||||
"# renovate: packageName=(?<packageName>.+?)\\s+.+?_VERSION \\?= (?<currentValue>.+?)\\s"
|
||||
|
||||
3
testdata/config_test_replicas.yaml
vendored
3
testdata/config_test_replicas.yaml
vendored
@@ -16,6 +16,9 @@ replicas:
|
||||
autoSetup: false
|
||||
interfaceName: eth3
|
||||
dhcpServerEnabled: false
|
||||
requestHeaders:
|
||||
FOO: bar
|
||||
Client-ID: xxxx
|
||||
cron: '*/15 * * * *'
|
||||
runOnStart: true
|
||||
printConfigOnly: true
|
||||
|
||||
7
testdata/e2e/resources/AdGuardHome.yaml
vendored
7
testdata/e2e/resources/AdGuardHome.yaml
vendored
@@ -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
|
||||
|
||||
1
testdata/e2e/values.yaml
vendored
1
testdata/e2e/values.yaml
vendored
@@ -2,6 +2,7 @@ replica:
|
||||
versions:
|
||||
- v0.107.40
|
||||
- v0.107.43
|
||||
- v0.107.63
|
||||
- latest
|
||||
|
||||
mode: env
|
||||
|
||||
Reference in New Issue
Block a user