Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a73f696ef6 | ||
|
|
2e93920931 | ||
|
|
3edb5222d6 | ||
|
|
d58c8f115e | ||
|
|
f8dd7e6136 | ||
|
|
9fd3694237 | ||
|
|
258ecae016 | ||
|
|
04a912fb56 | ||
|
|
cd75a5f46e | ||
|
|
87c578a07b | ||
|
|
28782fc364 | ||
|
|
7470a11547 | ||
|
|
0d35a77e1b | ||
|
|
bc8fc796ec | ||
|
|
da3b037009 | ||
|
|
4921af09a5 | ||
|
|
e7a2604268 | ||
|
|
cb624ea52b | ||
|
|
57612bae1f |
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. What version of AdGuardHome sync used?
|
||||||
|
2. What version of AdGuardHome us used?
|
||||||
|
3. How does the configuration look?
|
||||||
|
4. What is the error message?
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add log files or json responses from AdGuardHome to help explain your problem.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
10
.github/ISSUE_TEMPLATE/custom.md
vendored
Normal file
10
.github/ISSUE_TEMPLATE/custom.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
name: Custom issue template
|
||||||
|
about: Describe this issue template's purpose here.
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
|||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: go test ./... -coverprofile=coverage.out
|
run: make test
|
||||||
|
|
||||||
- name: Send coverage
|
- name: Send coverage
|
||||||
uses: shogo82148/actions-goveralls@v1
|
uses: shogo82148/actions-goveralls@v1
|
||||||
|
|||||||
10
Makefile
10
Makefile
@@ -16,10 +16,13 @@ tidy:
|
|||||||
go mod tidy
|
go mod tidy
|
||||||
|
|
||||||
# Run tests
|
# Run tests
|
||||||
test: tidy fmt vet
|
test: mocks tidy fmt vet
|
||||||
go test ./... -coverprofile=coverage.out
|
go test ./... -coverprofile=coverage.out
|
||||||
go tool cover -func=coverage.out
|
go tool cover -func=coverage.out
|
||||||
|
|
||||||
|
mocks: mockgen
|
||||||
|
mockgen -destination pkg/mocks/client/mock.go github.com/bakito/adguardhome-sync/pkg/client Client
|
||||||
|
|
||||||
release: semver
|
release: semver
|
||||||
@version=$$(semver); \
|
@version=$$(semver); \
|
||||||
git tag -s $$version -m"Release $$version"
|
git tag -s $$version -m"Release $$version"
|
||||||
@@ -31,4 +34,9 @@ test-release:
|
|||||||
semver:
|
semver:
|
||||||
ifeq (, $(shell which semver))
|
ifeq (, $(shell which semver))
|
||||||
$(shell go get -u github.com/bakito/semver)
|
$(shell go get -u github.com/bakito/semver)
|
||||||
|
endif
|
||||||
|
|
||||||
|
mockgen:
|
||||||
|
ifeq (, $(shell which mockgen))
|
||||||
|
$(shell go get github.com/golang/mock/mockgen@v1.5)
|
||||||
endif
|
endif
|
||||||
28
README.md
28
README.md
@@ -1,6 +1,7 @@
|
|||||||
[](https://github.com/bakito/adguardhome-sync/actions/workflows/go.yml)
|
[](https://github.com/bakito/adguardhome-sync/actions/workflows/go.yml)
|
||||||
[](https://goreportcard.com/report/github.com/bakito/adguardhome-sync)
|
[](https://goreportcard.com/report/github.com/bakito/adguardhome-sync)
|
||||||
[](https://coveralls.io/github/bakito/adguardhome-sync?branch=main)
|
[](https://coveralls.io/github/bakito/adguardhome-sync?branch=main)
|
||||||
|
|
||||||
# AdGuardHome sync
|
# AdGuardHome sync
|
||||||
|
|
||||||
Synchronize [AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) config to a replica instance.
|
Synchronize [AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) config to a replica instance.
|
||||||
@@ -13,6 +14,13 @@ Synchronize [AdGuardHome](https://github.com/AdguardTeam/AdGuardHome) config to
|
|||||||
- Services
|
- Services
|
||||||
- Clients
|
- Clients
|
||||||
|
|
||||||
|
### Setup of initial instances
|
||||||
|
|
||||||
|
New AdGuardHome replica instances can be automatically installed if enabled via the config autoSetup.
|
||||||
|
During automatic installation, the admin interface will be listening on port 3000 in runtime.
|
||||||
|
|
||||||
|
To skip automatic setup
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -21,7 +29,7 @@ go get -u github.com/bakito/adguardhome-sync
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
Both the origin and replica mist be initially setup via the Adguard Home installation wizard.
|
Both the origin instance must be initially setup via the AdguardHome installation wizard.
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
@@ -55,6 +63,7 @@ docker run -d \
|
|||||||
## docker compose
|
## docker compose
|
||||||
|
|
||||||
### config file
|
### config file
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
version: "2.1"
|
version: "2.1"
|
||||||
@@ -90,7 +99,9 @@ services:
|
|||||||
- REPLICA1_USERNAME=username
|
- REPLICA1_USERNAME=username
|
||||||
- REPLICA1_PASSWORD=password
|
- REPLICA1_PASSWORD=password
|
||||||
- REPLICA1_APIPATH=/some/path/control
|
- REPLICA1_APIPATH=/some/path/control
|
||||||
|
# - REPLICA1_AUTOSETUP=true # if true, AdGuardHome is automatically initialized.
|
||||||
- CRON=*/10 * * * * # run every 10 minutes
|
- CRON=*/10 * * * * # run every 10 minutes
|
||||||
|
- RUNONSTART=true
|
||||||
ports:
|
ports:
|
||||||
- 8080:8080
|
- 8080:8080
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -104,6 +115,9 @@ location: $HOME/.adguardhome-sync.yaml
|
|||||||
# cron expression to run in daemon mode. (default; "" = runs only once)
|
# cron expression to run in daemon mode. (default; "" = runs only once)
|
||||||
cron: "*/10 * * * *"
|
cron: "*/10 * * * *"
|
||||||
|
|
||||||
|
# runs the synchronisation on startup
|
||||||
|
runOnStart: true
|
||||||
|
|
||||||
origin:
|
origin:
|
||||||
# url of the origin instance
|
# url of the origin instance
|
||||||
url: https://192.168.1.2:3000
|
url: https://192.168.1.2:3000
|
||||||
@@ -128,6 +142,7 @@ replicas:
|
|||||||
- url: http://192.168.1.4
|
- url: http://192.168.1.4
|
||||||
username: username
|
username: username
|
||||||
password: password
|
password: password
|
||||||
|
# autoSetup: true # if true, AdGuardHome is automatically initialized.
|
||||||
|
|
||||||
# Configure the sync API server, disabled if api port is 0
|
# Configure the sync API server, disabled if api port is 0
|
||||||
api:
|
api:
|
||||||
@@ -138,3 +153,14 @@ api:
|
|||||||
password: password
|
password: password
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Log Level
|
||||||
|
|
||||||
|
The log level can be set with the environment variable: LOG_LEVEL
|
||||||
|
|
||||||
|
The following log levels are supported (default: info)
|
||||||
|
|
||||||
|
- debug
|
||||||
|
- info
|
||||||
|
- warn
|
||||||
|
- error
|
||||||
@@ -8,13 +8,14 @@ import (
|
|||||||
|
|
||||||
"github.com/bakito/adguardhome-sync/pkg/log"
|
"github.com/bakito/adguardhome-sync/pkg/log"
|
||||||
"github.com/bakito/adguardhome-sync/pkg/types"
|
"github.com/bakito/adguardhome-sync/pkg/types"
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
configCron = "cron"
|
configCron = "cron"
|
||||||
|
configRunOnStart = "runOnStart"
|
||||||
|
|
||||||
configAPIPort = "api.port"
|
configAPIPort = "api.port"
|
||||||
configAPIUsername = "api.username"
|
configAPIUsername = "api.username"
|
||||||
@@ -31,11 +32,13 @@ const (
|
|||||||
configReplicaUsername = "replica.username"
|
configReplicaUsername = "replica.username"
|
||||||
configReplicaPassword = "replica.password"
|
configReplicaPassword = "replica.password"
|
||||||
configReplicaInsecureSkipVerify = "replica.insecureSkipVerify"
|
configReplicaInsecureSkipVerify = "replica.insecureSkipVerify"
|
||||||
|
configReplicaAutoSetup = "replica.autoSetup"
|
||||||
|
|
||||||
envReplicasUsernameFormat = "REPLICA%s_USERNAME"
|
envReplicasUsernameFormat = "REPLICA%s_USERNAME"
|
||||||
envReplicasPasswordFormat = "REPLICA%s_PASSWORD"
|
envReplicasPasswordFormat = "REPLICA%s_PASSWORD"
|
||||||
envReplicasAPIPathFormat = "REPLICA%s_APIPATH"
|
envReplicasAPIPathFormat = "REPLICA%s_APIPATH"
|
||||||
envReplicasInsecureSkipVerifyFormat = "REPLICA%s_INSECURESKIPVERIFY"
|
envReplicasInsecureSkipVerifyFormat = "REPLICA%s_INSECURESKIPVERIFY"
|
||||||
|
envReplicasAutoSetup = "REPLICA%s_AUTOSETUP"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -126,6 +129,7 @@ func collectEnvReplicas() []types.AdGuardInstance {
|
|||||||
Password: os.Getenv(fmt.Sprintf(envReplicasPasswordFormat, sm[1])),
|
Password: os.Getenv(fmt.Sprintf(envReplicasPasswordFormat, sm[1])),
|
||||||
APIPath: os.Getenv(fmt.Sprintf(envReplicasAPIPathFormat, sm[1])),
|
APIPath: os.Getenv(fmt.Sprintf(envReplicasAPIPathFormat, sm[1])),
|
||||||
InsecureSkipVerify: strings.EqualFold(os.Getenv(fmt.Sprintf(envReplicasInsecureSkipVerifyFormat, sm[1])), "true"),
|
InsecureSkipVerify: strings.EqualFold(os.Getenv(fmt.Sprintf(envReplicasInsecureSkipVerifyFormat, sm[1])), "true"),
|
||||||
|
AutoSetup: strings.EqualFold(os.Getenv(fmt.Sprintf(envReplicasAutoSetup, sm[1])), "true"),
|
||||||
}
|
}
|
||||||
replicas = append(replicas, re)
|
replicas = append(replicas, re)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ func init() {
|
|||||||
rootCmd.AddCommand(doCmd)
|
rootCmd.AddCommand(doCmd)
|
||||||
doCmd.PersistentFlags().String("cron", "", "The cron expression to run in daemon mode")
|
doCmd.PersistentFlags().String("cron", "", "The cron expression to run in daemon mode")
|
||||||
_ = viper.BindPFlag(configCron, doCmd.PersistentFlags().Lookup("cron"))
|
_ = viper.BindPFlag(configCron, doCmd.PersistentFlags().Lookup("cron"))
|
||||||
|
doCmd.PersistentFlags().Bool("runOnStart", true, "Run the sync job on start.")
|
||||||
|
_ = viper.BindPFlag(configRunOnStart, doCmd.PersistentFlags().Lookup("runOnStart"))
|
||||||
doCmd.PersistentFlags().Int("api-port", 8080, "Sync API Port, the API endpoint will be started to enable remote triggering; if 0 port API is disabled.")
|
doCmd.PersistentFlags().Int("api-port", 8080, "Sync API Port, the API endpoint will be started to enable remote triggering; if 0 port API is disabled.")
|
||||||
_ = viper.BindPFlag(configAPIPort, doCmd.PersistentFlags().Lookup("api-port"))
|
_ = viper.BindPFlag(configAPIPort, doCmd.PersistentFlags().Lookup("api-port"))
|
||||||
doCmd.PersistentFlags().String("api-username", "", "Sync API username")
|
doCmd.PersistentFlags().String("api-username", "", "Sync API username")
|
||||||
@@ -54,6 +56,8 @@ func init() {
|
|||||||
_ = viper.BindPFlag(configReplicaUsername, doCmd.PersistentFlags().Lookup("replica-username"))
|
_ = viper.BindPFlag(configReplicaUsername, doCmd.PersistentFlags().Lookup("replica-username"))
|
||||||
doCmd.PersistentFlags().String("replica-password", "", "Replica instance password")
|
doCmd.PersistentFlags().String("replica-password", "", "Replica instance password")
|
||||||
_ = viper.BindPFlag(configReplicaPassword, doCmd.PersistentFlags().Lookup("replica-password"))
|
_ = viper.BindPFlag(configReplicaPassword, doCmd.PersistentFlags().Lookup("replica-password"))
|
||||||
doCmd.PersistentFlags().String("replica-insecure-skip-verify", "", "Enable Replica instance InsecureSkipVerify")
|
doCmd.PersistentFlags().Bool("replica-insecure-skip-verify", false, "Enable Replica instance InsecureSkipVerify")
|
||||||
_ = viper.BindPFlag(configReplicaInsecureSkipVerify, doCmd.PersistentFlags().Lookup("replica-insecure-skip-verify"))
|
_ = viper.BindPFlag(configReplicaInsecureSkipVerify, doCmd.PersistentFlags().Lookup("replica-insecure-skip-verify"))
|
||||||
|
doCmd.PersistentFlags().Bool("replica-auto-setup", false, "Enable automatic setup of new AdguardHome instances. This replaces the setup wizard.")
|
||||||
|
_ = viper.BindPFlag(configReplicaAutoSetup, doCmd.PersistentFlags().Lookup("replica-auto-setup"))
|
||||||
}
|
}
|
||||||
|
|||||||
6
go.mod
6
go.mod
@@ -3,14 +3,14 @@ module github.com/bakito/adguardhome-sync
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/go-resty/resty/v2 v2.4.0
|
github.com/go-resty/resty/v2 v2.6.0
|
||||||
|
github.com/golang/mock v1.5.0
|
||||||
github.com/google/uuid v1.2.0
|
github.com/google/uuid v1.2.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/onsi/ginkgo v1.16.0
|
github.com/onsi/ginkgo v1.16.1
|
||||||
github.com/onsi/gomega v1.11.0
|
github.com/onsi/gomega v1.11.0
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/spf13/cobra v1.1.3
|
github.com/spf13/cobra v1.1.3
|
||||||
github.com/spf13/viper v1.7.1
|
github.com/spf13/viper v1.7.1
|
||||||
go.uber.org/zap v1.16.0
|
go.uber.org/zap v1.16.0
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect
|
|
||||||
)
|
)
|
||||||
|
|||||||
18
go.sum
18
go.sum
@@ -46,8 +46,8 @@ github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9
|
|||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-resty/resty/v2 v2.4.0 h1:s6TItTLejEI+2mn98oijC5w/Rk2YU+OA6x0mnZN6r6k=
|
github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4=
|
||||||
github.com/go-resty/resty/v2 v2.4.0/go.mod h1:B88+xCTEwvfD94NOuE6GS1wMlnoKNY8eEiNizfNwOwA=
|
github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
@@ -57,6 +57,8 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er
|
|||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
|
||||||
|
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
@@ -152,8 +154,8 @@ github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+
|
|||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.16.0 h1:NBrNLB37exjJLxXtFOktx6CISBdS1aF8+7MwKlTV8U4=
|
github.com/onsi/ginkgo v1.16.1 h1:foqVmeWDD6yYpK+Yz3fHyNIxFYNxswxqNFjSKe+vI54=
|
||||||
github.com/onsi/ginkgo v1.16.0/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
github.com/onsi/ginkgo v1.16.1/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug=
|
github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug=
|
||||||
@@ -277,9 +279,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -309,8 +310,9 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw=
|
|
||||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
l = log.GetLogger("client")
|
l = log.GetLogger("client")
|
||||||
|
SetupNeededError = errors.New("setup needed")
|
||||||
)
|
)
|
||||||
|
|
||||||
// New create a new client
|
// New create a new client
|
||||||
func New(config types.AdGuardInstance) (Client, error) {
|
func New(config types.AdGuardInstance) (Client, error) {
|
||||||
|
|
||||||
var apiURL string
|
var apiURL string
|
||||||
if config.APIPath == "" {
|
if config.APIPath == "" {
|
||||||
apiURL = fmt.Sprintf("%s/control", config.URL)
|
apiURL = fmt.Sprintf("%s/control", config.URL)
|
||||||
@@ -42,6 +42,9 @@ func New(config types.AdGuardInstance) (Client, error) {
|
|||||||
cl = cl.SetBasicAuth(config.Username, config.Password)
|
cl = cl.SetBasicAuth(config.Username, config.Password)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// no redirect
|
||||||
|
cl.SetRedirectPolicy(resty.NoRedirectPolicy())
|
||||||
|
|
||||||
return &client{
|
return &client{
|
||||||
host: u.Host,
|
host: u.Host,
|
||||||
client: cl,
|
client: cl,
|
||||||
@@ -49,7 +52,7 @@ func New(config types.AdGuardInstance) (Client, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client AdGuard Home API client interface
|
// Client AdguardHome API client interface
|
||||||
type Client interface {
|
type Client interface {
|
||||||
Host() string
|
Host() string
|
||||||
|
|
||||||
@@ -74,7 +77,7 @@ type Client interface {
|
|||||||
SafeSearch() (bool, error)
|
SafeSearch() (bool, error)
|
||||||
ToggleSafeSearch(enable bool) error
|
ToggleSafeSearch(enable bool) error
|
||||||
|
|
||||||
Services() (*types.Services, error)
|
Services() (types.Services, error)
|
||||||
SetServices(services types.Services) error
|
SetServices(services types.Services) error
|
||||||
|
|
||||||
Clients() (*types.Clients, error)
|
Clients() (*types.Clients, error)
|
||||||
@@ -86,6 +89,7 @@ type Client interface {
|
|||||||
SetQueryLogConfig(enabled bool, interval int, anonymizeClientIP bool) error
|
SetQueryLogConfig(enabled bool, interval int, anonymizeClientIP bool) error
|
||||||
StatsConfig() (*types.IntervalConfig, error)
|
StatsConfig() (*types.IntervalConfig, error)
|
||||||
SetStatsConfig(interval int) error
|
SetStatsConfig(interval int) error
|
||||||
|
Setup() error
|
||||||
}
|
}
|
||||||
|
|
||||||
type client struct {
|
type client struct {
|
||||||
@@ -99,10 +103,22 @@ func (cl *client) Host() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cl *client) doGet(req *resty.Request, url string) error {
|
func (cl *client) doGet(req *resty.Request, url string) error {
|
||||||
|
rl := cl.log.With("method", "GET", "path", url)
|
||||||
|
if cl.client.UserInfo != nil {
|
||||||
|
rl = rl.With("username", cl.client.UserInfo.Username)
|
||||||
|
}
|
||||||
|
rl.Debug("do get")
|
||||||
resp, err := req.Get(url)
|
resp, err := req.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if resp != nil && resp.StatusCode() == http.StatusFound {
|
||||||
|
loc := resp.Header().Get("Location")
|
||||||
|
if loc == "/install.html" {
|
||||||
|
return SetupNeededError
|
||||||
|
}
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
rl.With("status", resp.StatusCode(), "body", string(resp.Body())).Debug("got response")
|
||||||
if resp.StatusCode() != http.StatusOK {
|
if resp.StatusCode() != http.StatusOK {
|
||||||
return errors.New(resp.Status())
|
return errors.New(resp.Status())
|
||||||
}
|
}
|
||||||
@@ -110,10 +126,16 @@ func (cl *client) doGet(req *resty.Request, url string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cl *client) doPost(req *resty.Request, url string) error {
|
func (cl *client) doPost(req *resty.Request, url string) error {
|
||||||
|
rl := cl.log.With("method", "POST", "path", url)
|
||||||
|
if cl.client.UserInfo != nil {
|
||||||
|
rl = rl.With("username", cl.client.UserInfo.Username)
|
||||||
|
}
|
||||||
|
rl.Debug("do post")
|
||||||
resp, err := req.Post(url)
|
resp, err := req.Post(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
rl.With("status", resp.StatusCode(), "body", string(resp.Body())).Debug("got response")
|
||||||
if resp.StatusCode() != http.StatusOK {
|
if resp.StatusCode() != http.StatusOK {
|
||||||
return errors.New(resp.Status())
|
return errors.New(resp.Status())
|
||||||
}
|
}
|
||||||
@@ -124,7 +146,6 @@ func (cl *client) Status() (*types.Status, error) {
|
|||||||
status := &types.Status{}
|
status := &types.Status{}
|
||||||
err := cl.doGet(cl.client.R().EnableTrace().SetResult(status), "status")
|
err := cl.doGet(cl.client.R().EnableTrace().SetResult(status), "status")
|
||||||
return status, err
|
return status, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *client) RewriteList() (*types.RewriteEntries, error) {
|
func (cl *client) RewriteList() (*types.RewriteEntries, error) {
|
||||||
@@ -204,7 +225,7 @@ func (cl *client) Filtering() (*types.FilteringStatus, error) {
|
|||||||
|
|
||||||
func (cl *client) AddFilters(whitelist bool, filters ...types.Filter) error {
|
func (cl *client) AddFilters(whitelist bool, filters ...types.Filter) error {
|
||||||
for _, f := range filters {
|
for _, f := range filters {
|
||||||
cl.log.With("url", f.URL, "whitelist", whitelist).Info("Add filter")
|
cl.log.With("url", f.URL, "whitelist", whitelist, "enabled", f.Enabled).Info("Add filter")
|
||||||
ff := &types.Filter{Name: f.Name, URL: f.URL, Whitelist: whitelist}
|
ff := &types.Filter{Name: f.Name, URL: f.URL, Whitelist: whitelist}
|
||||||
err := cl.doPost(cl.client.R().EnableTrace().SetBody(ff), "/filtering/add_url")
|
err := cl.doPost(cl.client.R().EnableTrace().SetBody(ff), "/filtering/add_url")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -216,7 +237,7 @@ func (cl *client) AddFilters(whitelist bool, filters ...types.Filter) error {
|
|||||||
|
|
||||||
func (cl *client) DeleteFilters(whitelist bool, filters ...types.Filter) error {
|
func (cl *client) DeleteFilters(whitelist bool, filters ...types.Filter) error {
|
||||||
for _, f := range filters {
|
for _, f := range filters {
|
||||||
cl.log.With("url", f.URL, "whitelist", whitelist).Info("Delete filter")
|
cl.log.With("url", f.URL, "whitelist", whitelist, "enabled", f.Enabled).Info("Delete filter")
|
||||||
ff := &types.Filter{URL: f.URL, Whitelist: whitelist}
|
ff := &types.Filter{URL: f.URL, Whitelist: whitelist}
|
||||||
err := cl.doPost(cl.client.R().EnableTrace().SetBody(ff), "/filtering/remove_url")
|
err := cl.doPost(cl.client.R().EnableTrace().SetBody(ff), "/filtering/remove_url")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -228,7 +249,7 @@ func (cl *client) DeleteFilters(whitelist bool, filters ...types.Filter) error {
|
|||||||
|
|
||||||
func (cl *client) UpdateFilters(whitelist bool, filters ...types.Filter) error {
|
func (cl *client) UpdateFilters(whitelist bool, filters ...types.Filter) error {
|
||||||
for _, f := range filters {
|
for _, f := range filters {
|
||||||
cl.log.With("url", f.URL, "whitelist", whitelist).Info("Update filter")
|
cl.log.With("url", f.URL, "whitelist", whitelist, "enabled", f.Enabled).Info("Update filter")
|
||||||
fu := &types.FilterUpdate{Whitelist: whitelist, URL: f.URL, Data: types.Filter{ID: f.ID, Name: f.Name, URL: f.URL, Whitelist: whitelist, Enabled: f.Enabled}}
|
fu := &types.FilterUpdate{Whitelist: whitelist, URL: f.URL, Data: types.Filter{ID: f.ID, Name: f.Name, URL: f.URL, Whitelist: whitelist, Enabled: f.Enabled}}
|
||||||
err := cl.doPost(cl.client.R().EnableTrace().SetBody(fu), "/filtering/set_url")
|
err := cl.doPost(cl.client.R().EnableTrace().SetBody(fu), "/filtering/set_url")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -261,9 +282,9 @@ func (cl *client) ToggleFiltering(enabled bool, interval int) error {
|
|||||||
}), "/filtering/config")
|
}), "/filtering/config")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cl *client) Services() (*types.Services, error) {
|
func (cl *client) Services() (types.Services, error) {
|
||||||
svcs := &types.Services{}
|
svcs := types.Services{}
|
||||||
err := cl.doGet(cl.client.R().EnableTrace().SetResult(svcs), "/blocked_services/list")
|
err := cl.doGet(cl.client.R().EnableTrace().SetResult(&svcs), "/blocked_services/list")
|
||||||
return svcs, err
|
return svcs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -336,3 +357,29 @@ func (cl *client) SetStatsConfig(interval int) error {
|
|||||||
cl.log.With("interval", interval).Info("Set stats config")
|
cl.log.With("interval", interval).Info("Set stats config")
|
||||||
return cl.doPost(cl.client.R().EnableTrace().SetBody(&types.IntervalConfig{Interval: interval}), "/stats_config")
|
return cl.doPost(cl.client.R().EnableTrace().SetBody(&types.IntervalConfig{Interval: interval}), "/stats_config")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cl *client) Setup() error {
|
||||||
|
cl.log.Info("Setup new AdguardHome instance")
|
||||||
|
cfg := &types.InstallConfig{
|
||||||
|
Web: types.InstallPort{
|
||||||
|
IP: "0.0.0.0",
|
||||||
|
Port: 3000,
|
||||||
|
Status: "",
|
||||||
|
CanAutofix: false,
|
||||||
|
},
|
||||||
|
DNS: types.InstallPort{
|
||||||
|
IP: "0.0.0.0",
|
||||||
|
Port: 53,
|
||||||
|
Status: "",
|
||||||
|
CanAutofix: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if cl.client.UserInfo != nil {
|
||||||
|
cfg.Username = cl.client.UserInfo.Username
|
||||||
|
cfg.Password = cl.client.UserInfo.Password
|
||||||
|
}
|
||||||
|
req := cl.client.R().EnableTrace().SetBody(cfg)
|
||||||
|
req.UserInfo = nil
|
||||||
|
return cl.doPost(req, "/install/configure")
|
||||||
|
}
|
||||||
|
|||||||
13
pkg/client/client_suite_test.go
Normal file
13
pkg/client/client_suite_test.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package client_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestClient(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "Client Suite")
|
||||||
|
}
|
||||||
349
pkg/client/client_test.go
Normal file
349
pkg/client/client_test.go
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
package client_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"github.com/bakito/adguardhome-sync/pkg/client"
|
||||||
|
"github.com/bakito/adguardhome-sync/pkg/types"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
username = uuid.NewString()
|
||||||
|
password = uuid.NewString()
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Client", func() {
|
||||||
|
|
||||||
|
var (
|
||||||
|
cl client.Client
|
||||||
|
ts *httptest.Server
|
||||||
|
)
|
||||||
|
AfterEach(func() {
|
||||||
|
if ts != nil {
|
||||||
|
ts.Close()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Host", func() {
|
||||||
|
It("should read the current host", func() {
|
||||||
|
cl, _ := client.New(types.AdGuardInstance{URL: "https://foo.bar:3000"})
|
||||||
|
host := cl.Host()
|
||||||
|
Ω(host).Should(Equal("foo.bar:3000"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Filtering", func() {
|
||||||
|
It("should read filtering status", func() {
|
||||||
|
ts, cl = ClientGet("filtering-status.json", "/filtering/status")
|
||||||
|
fs, err := cl.Filtering()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(fs.Enabled).Should(BeTrue())
|
||||||
|
Ω(fs.Filters).Should(HaveLen(2))
|
||||||
|
})
|
||||||
|
It("should enable protection", func() {
|
||||||
|
ts, cl = ClientPost("/filtering/config", `{"enabled":true,"interval":123}`)
|
||||||
|
err := cl.ToggleFiltering(true, 123)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should disable protection", func() {
|
||||||
|
ts, cl = ClientPost("/filtering/config", `{"enabled":false,"interval":123}`)
|
||||||
|
err := cl.ToggleFiltering(false, 123)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should call RefreshFilters", func() {
|
||||||
|
ts, cl = ClientPost("/filtering/refresh", `{"whitelist":true}`)
|
||||||
|
err := cl.RefreshFilters(true)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should add Filters", func() {
|
||||||
|
ts, cl = ClientPost("/filtering/add_url",
|
||||||
|
`{"id":0,"enabled":false,"url":"foo","name":"","rules_count":0,"whitelist":true}`,
|
||||||
|
`{"id":0,"enabled":false,"url":"bar","name":"","rules_count":0,"whitelist":true}`,
|
||||||
|
)
|
||||||
|
err := cl.AddFilters(true, types.Filter{URL: "foo"}, types.Filter{URL: "bar"})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should update Filters", func() {
|
||||||
|
ts, cl = ClientPost("/filtering/set_url",
|
||||||
|
`{"url":"foo","data":{"id":0,"enabled":false,"url":"foo","name":"","rules_count":0,"whitelist":true},"whitelist":true}`,
|
||||||
|
`{"url":"bar","data":{"id":0,"enabled":false,"url":"bar","name":"","rules_count":0,"whitelist":true},"whitelist":true}`,
|
||||||
|
)
|
||||||
|
err := cl.UpdateFilters(true, types.Filter{URL: "foo"}, types.Filter{URL: "bar"})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should delete Filters", func() {
|
||||||
|
ts, cl = ClientPost("/filtering/remove_url",
|
||||||
|
`{"id":0,"enabled":false,"url":"foo","name":"","rules_count":0,"whitelist":true}`,
|
||||||
|
`{"id":0,"enabled":false,"url":"bar","name":"","rules_count":0,"whitelist":true}`,
|
||||||
|
)
|
||||||
|
err := cl.DeleteFilters(true, types.Filter{URL: "foo"}, types.Filter{URL: "bar"})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("CustomRules", func() {
|
||||||
|
It("should set SetCustomRules", func() {
|
||||||
|
ts, cl = ClientPost("/filtering/set_rules", `foo
|
||||||
|
bar`)
|
||||||
|
err := cl.SetCustomRules([]string{"foo", "bar"})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Status", func() {
|
||||||
|
It("should read status", func() {
|
||||||
|
ts, cl = ClientGet("status.json", "/status")
|
||||||
|
fs, err := cl.Status()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(fs.DNSAddresses).Should(HaveLen(1))
|
||||||
|
Ω(fs.DNSAddresses[0]).Should(Equal("192.168.1.2"))
|
||||||
|
Ω(fs.Version).Should(Equal("v0.105.2"))
|
||||||
|
})
|
||||||
|
It("should return SetupNeededError", func() {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("Location", "/install.html")
|
||||||
|
w.WriteHeader(http.StatusFound)
|
||||||
|
}))
|
||||||
|
cl, err := client.New(types.AdGuardInstance{URL: ts.URL})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
_, err = cl.Status()
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
Ω(err).Should(Equal(client.SetupNeededError))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Setup", func() {
|
||||||
|
It("should add setup the instance", func() {
|
||||||
|
ts, cl = ClientPost("/install/configure", fmt.Sprintf(`{"web":{"ip":"0.0.0.0","port":3000,"status":"","can_autofix":false},"dns":{"ip":"0.0.0.0","port":53,"status":"","can_autofix":false},"username":"%s","password":"%s"}`, username, password))
|
||||||
|
err := cl.Setup()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("RewriteList", func() {
|
||||||
|
It("should read RewriteList", func() {
|
||||||
|
ts, cl = ClientGet("rewrite-list.json", "/rewrite/list")
|
||||||
|
rwl, err := cl.RewriteList()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(*rwl).Should(HaveLen(2))
|
||||||
|
})
|
||||||
|
It("should add RewriteList", func() {
|
||||||
|
ts, cl = ClientPost("/rewrite/add", `{"domain":"foo","answer":"foo"}`, `{"domain":"bar","answer":"bar"}`)
|
||||||
|
err := cl.AddRewriteEntries(types.RewriteEntry{Answer: "foo", Domain: "foo"}, types.RewriteEntry{Answer: "bar", Domain: "bar"})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should delete RewriteList", func() {
|
||||||
|
ts, cl = ClientPost("/rewrite/delete", `{"domain":"foo","answer":"foo"}`, `{"domain":"bar","answer":"bar"}`)
|
||||||
|
err := cl.DeleteRewriteEntries(types.RewriteEntry{Answer: "foo", Domain: "foo"}, types.RewriteEntry{Answer: "bar", Domain: "bar"})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("SafeBrowsing", func() {
|
||||||
|
It("should read safebrowsing status", func() {
|
||||||
|
ts, cl = ClientGet("safebrowsing-status.json", "/safebrowsing/status")
|
||||||
|
sb, err := cl.SafeBrowsing()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(sb).Should(BeTrue())
|
||||||
|
})
|
||||||
|
It("should enable safebrowsing", func() {
|
||||||
|
ts, cl = ClientPost("/safebrowsing/enable", "")
|
||||||
|
err := cl.ToggleSafeBrowsing(true)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should disable safebrowsing", func() {
|
||||||
|
ts, cl = ClientPost("/safebrowsing/disable", "")
|
||||||
|
err := cl.ToggleSafeBrowsing(false)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("SafeSearch", func() {
|
||||||
|
It("should read safesearch status", func() {
|
||||||
|
ts, cl = ClientGet("safesearch-status.json", "/safesearch/status")
|
||||||
|
ss, err := cl.SafeSearch()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(ss).Should(BeTrue())
|
||||||
|
})
|
||||||
|
It("should enable safesearch", func() {
|
||||||
|
ts, cl = ClientPost("/safesearch/enable", "")
|
||||||
|
err := cl.ToggleSafeSearch(true)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should disable safesearch", func() {
|
||||||
|
ts, cl = ClientPost("/safesearch/disable", "")
|
||||||
|
err := cl.ToggleSafeSearch(false)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Parental", func() {
|
||||||
|
It("should read parental status", func() {
|
||||||
|
ts, cl = ClientGet("parental-status.json", "/parental/status")
|
||||||
|
p, err := cl.Parental()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(p).Should(BeTrue())
|
||||||
|
})
|
||||||
|
It("should enable parental", func() {
|
||||||
|
ts, cl = ClientPost("/parental/enable", "")
|
||||||
|
err := cl.ToggleParental(true)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should disable parental", func() {
|
||||||
|
ts, cl = ClientPost("/parental/disable", "")
|
||||||
|
err := cl.ToggleParental(false)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Protection", func() {
|
||||||
|
It("should enable protection", func() {
|
||||||
|
ts, cl = ClientPost("/dns_config", `{"protection_enabled":true}`)
|
||||||
|
err := cl.ToggleProtection(true)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should disable protection", func() {
|
||||||
|
ts, cl = ClientPost("/dns_config", `{"protection_enabled":false}`)
|
||||||
|
err := cl.ToggleProtection(false)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Services", func() {
|
||||||
|
It("should read Services", func() {
|
||||||
|
ts, cl = ClientGet("blockedservices-list.json", "/blocked_services/list")
|
||||||
|
s, err := cl.Services()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(s).Should(HaveLen(2))
|
||||||
|
})
|
||||||
|
It("should set Services", func() {
|
||||||
|
ts, cl = ClientPost("/blocked_services/set", `["foo","bar"]`)
|
||||||
|
err := cl.SetServices([]string{"foo", "bar"})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Clients", func() {
|
||||||
|
It("should read Clients", func() {
|
||||||
|
ts, cl = ClientGet("clients.json", "/clients")
|
||||||
|
c, err := cl.Clients()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(c.Clients).Should(HaveLen(2))
|
||||||
|
})
|
||||||
|
It("should add Clients", func() {
|
||||||
|
ts, cl = ClientPost("/clients/add",
|
||||||
|
`{"ids":["id"],"use_global_settings":false,"use_global_blocked_services":false,"name":"foo","filtering_enabled":false,"parental_enabled":false,"safesearch_enabled":false,"safebrowsing_enabled":false,"disallowed":false,"disallowed_rule":""}`,
|
||||||
|
)
|
||||||
|
err := cl.AddClients(types.Client{Name: "foo", Ids: []string{"id"}})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should update Clients", func() {
|
||||||
|
ts, cl = ClientPost("/clients/update",
|
||||||
|
`{"name":"foo","data":{"ids":["id"],"use_global_settings":false,"use_global_blocked_services":false,"name":"foo","filtering_enabled":false,"parental_enabled":false,"safesearch_enabled":false,"safebrowsing_enabled":false,"disallowed":false,"disallowed_rule":""}}`,
|
||||||
|
)
|
||||||
|
err := cl.UpdateClients(types.Client{Name: "foo", Ids: []string{"id"}})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should delete Clients", func() {
|
||||||
|
ts, cl = ClientPost("/clients/delete",
|
||||||
|
`{"ids":["id"],"use_global_settings":false,"use_global_blocked_services":false,"name":"foo","filtering_enabled":false,"parental_enabled":false,"safesearch_enabled":false,"safebrowsing_enabled":false,"disallowed":false,"disallowed_rule":""}`,
|
||||||
|
)
|
||||||
|
err := cl.DeleteClients(types.Client{Name: "foo", Ids: []string{"id"}})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("QueryLogConfig", func() {
|
||||||
|
It("should read QueryLogConfig", func() {
|
||||||
|
ts, cl = ClientGet("querylog_info.json", "/querylog_info")
|
||||||
|
qlc, err := cl.QueryLogConfig()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(qlc.Enabled).Should(BeTrue())
|
||||||
|
Ω(qlc.Interval).Should(Equal(90))
|
||||||
|
})
|
||||||
|
It("should set QueryLogConfig", func() {
|
||||||
|
ts, cl = ClientPost("/querylog_config", `{"enabled":true,"interval":123,"anonymize_client_ip":true}`)
|
||||||
|
err := cl.SetQueryLogConfig(true, 123, true)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Context("StatsConfig", func() {
|
||||||
|
It("should read StatsConfig", func() {
|
||||||
|
ts, cl = ClientGet("stats_info.json", "/stats_info")
|
||||||
|
sc, err := cl.StatsConfig()
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(sc.Interval).Should(Equal(1))
|
||||||
|
})
|
||||||
|
It("should set StatsConfig", func() {
|
||||||
|
ts, cl = ClientPost("/stats_config", `{"interval":123}`)
|
||||||
|
err := cl.SetStatsConfig(123)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("helper functions", func() {
|
||||||
|
var (
|
||||||
|
cl client.Client
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
}))
|
||||||
|
var err error
|
||||||
|
cl, err = client.New(types.AdGuardInstance{URL: ts.URL})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
Context("doGet", func() {
|
||||||
|
It("should return an error on status code != 200", func() {
|
||||||
|
_, err := cl.Status()
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
Ω(err.Error()).Should(Equal("401 Unauthorized"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("doPost", func() {
|
||||||
|
It("should return an error on status code != 200", func() {
|
||||||
|
err := cl.SetStatsConfig(123)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
Ω(err.Error()).Should(Equal("401 Unauthorized"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
func ClientGet(file string, path string) (*httptest.Server, client.Client) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
Ω(r.URL.Path).Should(Equal(types.DefaultAPIPath + path))
|
||||||
|
b, err := ioutil.ReadFile(filepath.Join("../../testdata", file))
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, err = w.Write(b)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
}))
|
||||||
|
cl, err := client.New(types.AdGuardInstance{URL: ts.URL})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
return ts, cl
|
||||||
|
}
|
||||||
|
|
||||||
|
func ClientPost(path string, content ...string) (*httptest.Server, client.Client) {
|
||||||
|
index := 0
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
Ω(r.URL.Path).Should(Equal(types.DefaultAPIPath + path))
|
||||||
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(body).Should(Equal([]byte(content[index])))
|
||||||
|
index++
|
||||||
|
}))
|
||||||
|
|
||||||
|
cl, err := client.New(types.AdGuardInstance{URL: ts.URL, Username: username, Password: password})
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
return ts, cl
|
||||||
|
}
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"go.uber.org/zap/zapcore"
|
"go.uber.org/zap/zapcore"
|
||||||
)
|
)
|
||||||
|
|
||||||
const logHistorySize = 50
|
const (
|
||||||
|
logHistorySize = 50
|
||||||
|
envLogLevel = "LOG_LEVEL"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rootLogger *zap.Logger
|
rootLogger *zap.Logger
|
||||||
@@ -20,6 +25,12 @@ func GetLogger(name string) *zap.SugaredLogger {
|
|||||||
func init() {
|
func init() {
|
||||||
level := zap.InfoLevel
|
level := zap.InfoLevel
|
||||||
|
|
||||||
|
if lvl, ok := os.LookupEnv(envLogLevel); ok {
|
||||||
|
if err := level.Set(lvl); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cfg := zap.Config{
|
cfg := zap.Config{
|
||||||
Level: zap.NewAtomicLevelAt(level),
|
Level: zap.NewAtomicLevelAt(level),
|
||||||
Development: false,
|
Development: false,
|
||||||
|
|||||||
500
pkg/mocks/client/mock.go
Normal file
500
pkg/mocks/client/mock.go
Normal file
@@ -0,0 +1,500 @@
|
|||||||
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
|
// Source: github.com/bakito/adguardhome-sync/pkg/client (interfaces: Client)
|
||||||
|
|
||||||
|
// Package mock_client is a generated GoMock package.
|
||||||
|
package mock_client
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
|
||||||
|
types "github.com/bakito/adguardhome-sync/pkg/types"
|
||||||
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockClient is a mock of Client interface.
|
||||||
|
type MockClient struct {
|
||||||
|
ctrl *gomock.Controller
|
||||||
|
recorder *MockClientMockRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockClientMockRecorder is the mock recorder for MockClient.
|
||||||
|
type MockClientMockRecorder struct {
|
||||||
|
mock *MockClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockClient creates a new mock instance.
|
||||||
|
func NewMockClient(ctrl *gomock.Controller) *MockClient {
|
||||||
|
mock := &MockClient{ctrl: ctrl}
|
||||||
|
mock.recorder = &MockClientMockRecorder{mock}
|
||||||
|
return mock
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||||
|
func (m *MockClient) EXPECT() *MockClientMockRecorder {
|
||||||
|
return m.recorder
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddClients mocks base method.
|
||||||
|
func (m *MockClient) AddClients(arg0 ...types.Client) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{}
|
||||||
|
for _, a := range arg0 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "AddClients", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddClients indicates an expected call of AddClients.
|
||||||
|
func (mr *MockClientMockRecorder) AddClients(arg0 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddClients", reflect.TypeOf((*MockClient)(nil).AddClients), arg0...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFilters mocks base method.
|
||||||
|
func (m *MockClient) AddFilters(arg0 bool, arg1 ...types.Filter) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{arg0}
|
||||||
|
for _, a := range arg1 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "AddFilters", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddFilters indicates an expected call of AddFilters.
|
||||||
|
func (mr *MockClientMockRecorder) AddFilters(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]interface{}{arg0}, arg1...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddFilters", reflect.TypeOf((*MockClient)(nil).AddFilters), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRewriteEntries mocks base method.
|
||||||
|
func (m *MockClient) AddRewriteEntries(arg0 ...types.RewriteEntry) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{}
|
||||||
|
for _, a := range arg0 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "AddRewriteEntries", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddRewriteEntries indicates an expected call of AddRewriteEntries.
|
||||||
|
func (mr *MockClientMockRecorder) AddRewriteEntries(arg0 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRewriteEntries", reflect.TypeOf((*MockClient)(nil).AddRewriteEntries), arg0...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clients mocks base method.
|
||||||
|
func (m *MockClient) Clients() (*types.Clients, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Clients")
|
||||||
|
ret0, _ := ret[0].(*types.Clients)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clients indicates an expected call of Clients.
|
||||||
|
func (mr *MockClientMockRecorder) Clients() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Clients", reflect.TypeOf((*MockClient)(nil).Clients))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteClients mocks base method.
|
||||||
|
func (m *MockClient) DeleteClients(arg0 ...types.Client) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{}
|
||||||
|
for _, a := range arg0 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "DeleteClients", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteClients indicates an expected call of DeleteClients.
|
||||||
|
func (mr *MockClientMockRecorder) DeleteClients(arg0 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteClients", reflect.TypeOf((*MockClient)(nil).DeleteClients), arg0...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFilters mocks base method.
|
||||||
|
func (m *MockClient) DeleteFilters(arg0 bool, arg1 ...types.Filter) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{arg0}
|
||||||
|
for _, a := range arg1 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "DeleteFilters", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteFilters indicates an expected call of DeleteFilters.
|
||||||
|
func (mr *MockClientMockRecorder) DeleteFilters(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]interface{}{arg0}, arg1...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFilters", reflect.TypeOf((*MockClient)(nil).DeleteFilters), varargs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRewriteEntries mocks base method.
|
||||||
|
func (m *MockClient) DeleteRewriteEntries(arg0 ...types.RewriteEntry) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{}
|
||||||
|
for _, a := range arg0 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "DeleteRewriteEntries", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteRewriteEntries indicates an expected call of DeleteRewriteEntries.
|
||||||
|
func (mr *MockClientMockRecorder) DeleteRewriteEntries(arg0 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRewriteEntries", reflect.TypeOf((*MockClient)(nil).DeleteRewriteEntries), arg0...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtering mocks base method.
|
||||||
|
func (m *MockClient) Filtering() (*types.FilteringStatus, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Filtering")
|
||||||
|
ret0, _ := ret[0].(*types.FilteringStatus)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filtering indicates an expected call of Filtering.
|
||||||
|
func (mr *MockClientMockRecorder) Filtering() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Filtering", reflect.TypeOf((*MockClient)(nil).Filtering))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Host mocks base method.
|
||||||
|
func (m *MockClient) Host() string {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Host")
|
||||||
|
ret0, _ := ret[0].(string)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Host indicates an expected call of Host.
|
||||||
|
func (mr *MockClientMockRecorder) Host() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockClient)(nil).Host))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parental mocks base method.
|
||||||
|
func (m *MockClient) Parental() (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Parental")
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parental indicates an expected call of Parental.
|
||||||
|
func (mr *MockClientMockRecorder) Parental() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Parental", reflect.TypeOf((*MockClient)(nil).Parental))
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryLogConfig mocks base method.
|
||||||
|
func (m *MockClient) QueryLogConfig() (*types.QueryLogConfig, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "QueryLogConfig")
|
||||||
|
ret0, _ := ret[0].(*types.QueryLogConfig)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// QueryLogConfig indicates an expected call of QueryLogConfig.
|
||||||
|
func (mr *MockClientMockRecorder) QueryLogConfig() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryLogConfig", reflect.TypeOf((*MockClient)(nil).QueryLogConfig))
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefreshFilters mocks base method.
|
||||||
|
func (m *MockClient) RefreshFilters(arg0 bool) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "RefreshFilters", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// RefreshFilters indicates an expected call of RefreshFilters.
|
||||||
|
func (mr *MockClientMockRecorder) RefreshFilters(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RefreshFilters", reflect.TypeOf((*MockClient)(nil).RefreshFilters), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RewriteList mocks base method.
|
||||||
|
func (m *MockClient) RewriteList() (*types.RewriteEntries, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "RewriteList")
|
||||||
|
ret0, _ := ret[0].(*types.RewriteEntries)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// RewriteList indicates an expected call of RewriteList.
|
||||||
|
func (mr *MockClientMockRecorder) RewriteList() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RewriteList", reflect.TypeOf((*MockClient)(nil).RewriteList))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeBrowsing mocks base method.
|
||||||
|
func (m *MockClient) SafeBrowsing() (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SafeBrowsing")
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeBrowsing indicates an expected call of SafeBrowsing.
|
||||||
|
func (mr *MockClientMockRecorder) SafeBrowsing() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SafeBrowsing", reflect.TypeOf((*MockClient)(nil).SafeBrowsing))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeSearch mocks base method.
|
||||||
|
func (m *MockClient) SafeSearch() (bool, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SafeSearch")
|
||||||
|
ret0, _ := ret[0].(bool)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeSearch indicates an expected call of SafeSearch.
|
||||||
|
func (mr *MockClientMockRecorder) SafeSearch() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SafeSearch", reflect.TypeOf((*MockClient)(nil).SafeSearch))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Services mocks base method.
|
||||||
|
func (m *MockClient) Services() (types.Services, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Services")
|
||||||
|
ret0, _ := ret[0].(types.Services)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Services indicates an expected call of Services.
|
||||||
|
func (mr *MockClientMockRecorder) Services() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Services", reflect.TypeOf((*MockClient)(nil).Services))
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCustomRules mocks base method.
|
||||||
|
func (m *MockClient) SetCustomRules(arg0 types.UserRules) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SetCustomRules", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetCustomRules indicates an expected call of SetCustomRules.
|
||||||
|
func (mr *MockClientMockRecorder) SetCustomRules(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCustomRules", reflect.TypeOf((*MockClient)(nil).SetCustomRules), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetQueryLogConfig mocks base method.
|
||||||
|
func (m *MockClient) SetQueryLogConfig(arg0 bool, arg1 int, arg2 bool) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SetQueryLogConfig", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetQueryLogConfig indicates an expected call of SetQueryLogConfig.
|
||||||
|
func (mr *MockClientMockRecorder) SetQueryLogConfig(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetQueryLogConfig", reflect.TypeOf((*MockClient)(nil).SetQueryLogConfig), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetServices mocks base method.
|
||||||
|
func (m *MockClient) SetServices(arg0 types.Services) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SetServices", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetServices indicates an expected call of SetServices.
|
||||||
|
func (mr *MockClientMockRecorder) SetServices(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetServices", reflect.TypeOf((*MockClient)(nil).SetServices), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStatsConfig mocks base method.
|
||||||
|
func (m *MockClient) SetStatsConfig(arg0 int) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "SetStatsConfig", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStatsConfig indicates an expected call of SetStatsConfig.
|
||||||
|
func (mr *MockClientMockRecorder) SetStatsConfig(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetStatsConfig", reflect.TypeOf((*MockClient)(nil).SetStatsConfig), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup mocks base method.
|
||||||
|
func (m *MockClient) Setup() error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Setup")
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup indicates an expected call of Setup.
|
||||||
|
func (mr *MockClientMockRecorder) Setup() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Setup", reflect.TypeOf((*MockClient)(nil).Setup))
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatsConfig mocks base method.
|
||||||
|
func (m *MockClient) StatsConfig() (*types.IntervalConfig, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "StatsConfig")
|
||||||
|
ret0, _ := ret[0].(*types.IntervalConfig)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatsConfig indicates an expected call of StatsConfig.
|
||||||
|
func (mr *MockClientMockRecorder) StatsConfig() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StatsConfig", reflect.TypeOf((*MockClient)(nil).StatsConfig))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status mocks base method.
|
||||||
|
func (m *MockClient) Status() (*types.Status, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "Status")
|
||||||
|
ret0, _ := ret[0].(*types.Status)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status indicates an expected call of Status.
|
||||||
|
func (mr *MockClientMockRecorder) Status() *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Status", reflect.TypeOf((*MockClient)(nil).Status))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleFiltering mocks base method.
|
||||||
|
func (m *MockClient) ToggleFiltering(arg0 bool, arg1 int) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ToggleFiltering", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleFiltering indicates an expected call of ToggleFiltering.
|
||||||
|
func (mr *MockClientMockRecorder) ToggleFiltering(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToggleFiltering", reflect.TypeOf((*MockClient)(nil).ToggleFiltering), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleParental mocks base method.
|
||||||
|
func (m *MockClient) ToggleParental(arg0 bool) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ToggleParental", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleParental indicates an expected call of ToggleParental.
|
||||||
|
func (mr *MockClientMockRecorder) ToggleParental(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToggleParental", reflect.TypeOf((*MockClient)(nil).ToggleParental), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleProtection mocks base method.
|
||||||
|
func (m *MockClient) ToggleProtection(arg0 bool) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ToggleProtection", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleProtection indicates an expected call of ToggleProtection.
|
||||||
|
func (mr *MockClientMockRecorder) ToggleProtection(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToggleProtection", reflect.TypeOf((*MockClient)(nil).ToggleProtection), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleSafeBrowsing mocks base method.
|
||||||
|
func (m *MockClient) ToggleSafeBrowsing(arg0 bool) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ToggleSafeBrowsing", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleSafeBrowsing indicates an expected call of ToggleSafeBrowsing.
|
||||||
|
func (mr *MockClientMockRecorder) ToggleSafeBrowsing(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToggleSafeBrowsing", reflect.TypeOf((*MockClient)(nil).ToggleSafeBrowsing), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleSafeSearch mocks base method.
|
||||||
|
func (m *MockClient) ToggleSafeSearch(arg0 bool) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ToggleSafeSearch", arg0)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToggleSafeSearch indicates an expected call of ToggleSafeSearch.
|
||||||
|
func (mr *MockClientMockRecorder) ToggleSafeSearch(arg0 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ToggleSafeSearch", reflect.TypeOf((*MockClient)(nil).ToggleSafeSearch), arg0)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateClients mocks base method.
|
||||||
|
func (m *MockClient) UpdateClients(arg0 ...types.Client) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{}
|
||||||
|
for _, a := range arg0 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "UpdateClients", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateClients indicates an expected call of UpdateClients.
|
||||||
|
func (mr *MockClientMockRecorder) UpdateClients(arg0 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateClients", reflect.TypeOf((*MockClient)(nil).UpdateClients), arg0...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFilters mocks base method.
|
||||||
|
func (m *MockClient) UpdateFilters(arg0 bool, arg1 ...types.Filter) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
varargs := []interface{}{arg0}
|
||||||
|
for _, a := range arg1 {
|
||||||
|
varargs = append(varargs, a)
|
||||||
|
}
|
||||||
|
ret := m.ctrl.Call(m, "UpdateFilters", varargs...)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateFilters indicates an expected call of UpdateFilters.
|
||||||
|
func (mr *MockClientMockRecorder) UpdateFilters(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
varargs := append([]interface{}{arg0}, arg1...)
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateFilters", reflect.TypeOf((*MockClient)(nil).UpdateFilters), varargs...)
|
||||||
|
}
|
||||||
121
pkg/sync/sync.go
121
pkg/sync/sync.go
@@ -1,6 +1,7 @@
|
|||||||
package sync
|
package sync
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/bakito/adguardhome-sync/pkg/client"
|
"github.com/bakito/adguardhome-sync/pkg/client"
|
||||||
@@ -26,8 +27,13 @@ func Sync(cfg *types.Config) error {
|
|||||||
return fmt.Errorf("no replicas configured")
|
return fmt.Errorf("no replicas configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg.Origin.AutoSetup = false
|
||||||
|
|
||||||
w := &worker{
|
w := &worker{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
|
createClient: func(ai types.AdGuardInstance) (client.Client, error) {
|
||||||
|
return client.New(ai)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if cfg.Cron != "" {
|
if cfg.Cron != "" {
|
||||||
w.cron = cron.New()
|
w.cron = cron.New()
|
||||||
@@ -45,7 +51,9 @@ func Sync(cfg *types.Config) error {
|
|||||||
} else {
|
} else {
|
||||||
w.cron.Run()
|
w.cron.Run()
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
if cfg.RunOnStart {
|
||||||
|
l.With("version", version.Version).Info("Run on startup")
|
||||||
w.sync()
|
w.sync()
|
||||||
}
|
}
|
||||||
if cfg.API.Port != 0 {
|
if cfg.API.Port != 0 {
|
||||||
@@ -55,9 +63,10 @@ func Sync(cfg *types.Config) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type worker struct {
|
type worker struct {
|
||||||
cfg *types.Config
|
cfg *types.Config
|
||||||
running bool
|
running bool
|
||||||
cron *cron.Cron
|
cron *cron.Cron
|
||||||
|
createClient func(instance types.AdGuardInstance) (client.Client, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) sync() {
|
func (w *worker) sync() {
|
||||||
@@ -68,7 +77,7 @@ func (w *worker) sync() {
|
|||||||
w.running = true
|
w.running = true
|
||||||
defer func() { w.running = false }()
|
defer func() { w.running = false }()
|
||||||
|
|
||||||
oc, err := client.New(w.cfg.Origin)
|
oc, err := w.createClient(w.cfg.Origin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.With("error", err, "url", w.cfg.Origin.URL).Error("Error creating origin client")
|
l.With("error", err, "url", w.cfg.Origin.URL).Error("Error creating origin client")
|
||||||
return
|
return
|
||||||
@@ -77,7 +86,6 @@ func (w *worker) sync() {
|
|||||||
sl := l.With("from", oc.Host())
|
sl := l.With("from", oc.Host())
|
||||||
|
|
||||||
o := &origin{}
|
o := &origin{}
|
||||||
|
|
||||||
o.status, err = oc.Status()
|
o.status, err = oc.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sl.With("error", err).Error("Error getting origin status")
|
sl.With("error", err).Error("Error getting origin status")
|
||||||
@@ -141,7 +149,7 @@ func (w *worker) sync() {
|
|||||||
|
|
||||||
func (w *worker) syncTo(l *zap.SugaredLogger, o *origin, replica types.AdGuardInstance) {
|
func (w *worker) syncTo(l *zap.SugaredLogger, o *origin, replica types.AdGuardInstance) {
|
||||||
|
|
||||||
rc, err := client.New(replica)
|
rc, err := w.createClient(replica)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.With("error", err, "url", replica.URL).Error("Error creating replica client")
|
l.With("error", err, "url", replica.URL).Error("Error creating replica client")
|
||||||
return
|
return
|
||||||
@@ -150,61 +158,76 @@ func (w *worker) syncTo(l *zap.SugaredLogger, o *origin, replica types.AdGuardIn
|
|||||||
rl := l.With("to", rc.Host())
|
rl := l.With("to", rc.Host())
|
||||||
rl.Info("Start sync")
|
rl.Info("Start sync")
|
||||||
|
|
||||||
rs, err := rc.Status()
|
rs, err := w.statusWithSetup(rl, replica, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.With("error", err).Error("Error getting replica status")
|
rl.With("error", err).Error("Error getting replica status")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.status.Version != rs.Version {
|
if o.status.Version != rs.Version {
|
||||||
l.With("originVersion", o.status.Version, "replicaVersion", rs.Version).Warn("Versions do not match")
|
rl.With("originVersion", o.status.Version, "replicaVersion", rs.Version).Warn("Versions do not match")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = w.syncGeneralSettings(o, rs, rc)
|
err = w.syncGeneralSettings(o, rs, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.With("error", err).Error("Error syncing general settings")
|
rl.With("error", err).Error("Error syncing general settings")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = w.syncConfigs(o, rs, rc)
|
err = w.syncConfigs(o, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.With("error", err).Error("Error syncing configs")
|
rl.With("error", err).Error("Error syncing configs")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = w.syncRewrites(o.rewrites, rc)
|
err = w.syncRewrites(o.rewrites, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.With("error", err).Error("Error syncing rewrites")
|
rl.With("error", err).Error("Error syncing rewrites")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = w.syncFilters(o.filters, rc)
|
err = w.syncFilters(o.filters, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.With("error", err).Error("Error syncing filters")
|
rl.With("error", err).Error("Error syncing filters")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = w.syncServices(o.services, rc)
|
err = w.syncServices(o.services, rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.With("error", err).Error("Error syncing services")
|
rl.With("error", err).Error("Error syncing services")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = w.syncClients(o.clients, rc); err != nil {
|
if err = w.syncClients(o.clients, rc); err != nil {
|
||||||
l.With("error", err).Error("Error syncing clients")
|
rl.With("error", err).Error("Error syncing clients")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.Info("Sync done")
|
rl.Info("Sync done")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) syncServices(os *types.Services, replica client.Client) error {
|
func (w *worker) statusWithSetup(rl *zap.SugaredLogger, replica types.AdGuardInstance, rc client.Client) (*types.Status, error) {
|
||||||
|
rs, err := rc.Status()
|
||||||
|
if err != nil {
|
||||||
|
if replica.AutoSetup && errors.Is(err, client.SetupNeededError) {
|
||||||
|
if serr := rc.Setup(); serr != nil {
|
||||||
|
rl.With("error", serr).Error("Error setup AdGuardHome")
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rc.Status()
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *worker) syncServices(os types.Services, replica client.Client) error {
|
||||||
rs, err := replica.Services()
|
rs, err := replica.Services()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !os.Equals(rs) {
|
if !os.Equals(rs) {
|
||||||
if err := replica.SetServices(*os); err != nil {
|
if err := replica.SetServices(os); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,40 +240,10 @@ func (w *worker) syncFilters(of *types.FilteringStatus, replica client.Client) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fa, fu, fd := rf.Filters.Merge(of.Filters)
|
if err = w.syncFilterType(of.Filters, rf.Filters, false, replica); err != nil {
|
||||||
|
|
||||||
if err = replica.AddFilters(false, fa...); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err = replica.UpdateFilters(false, fu...); err != nil {
|
if err = w.syncFilterType(of.WhitelistFilters, rf.WhitelistFilters, true, replica); err != nil {
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fa) > 0 || len(fu) > 0 {
|
|
||||||
if err = replica.RefreshFilters(false); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = replica.DeleteFilters(false, fd...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fa, fu, fd = rf.WhitelistFilters.Merge(of.WhitelistFilters)
|
|
||||||
if err = replica.AddFilters(true, fa...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err = replica.UpdateFilters(true, fu...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fa) > 0 || len(fu) > 0 {
|
|
||||||
if err = replica.RefreshFilters(true); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = replica.DeleteFilters(true, fd...); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,6 +259,28 @@ func (w *worker) syncFilters(of *types.FilteringStatus, replica client.Client) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *worker) syncFilterType(of types.Filters, rFilters types.Filters, whitelist bool, replica client.Client) error {
|
||||||
|
fa, fu, fd := rFilters.Merge(of)
|
||||||
|
|
||||||
|
if err := replica.AddFilters(whitelist, fa...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := replica.UpdateFilters(whitelist, fu...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fa) > 0 || len(fu) > 0 {
|
||||||
|
if err := replica.RefreshFilters(whitelist); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := replica.DeleteFilters(whitelist, fd...); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (w *worker) syncRewrites(or *types.RewriteEntries, replica client.Client) error {
|
func (w *worker) syncRewrites(or *types.RewriteEntries, replica client.Client) error {
|
||||||
|
|
||||||
replicaRewrites, err := replica.RewriteList()
|
replicaRewrites, err := replica.RewriteList()
|
||||||
@@ -334,7 +349,7 @@ func (w *worker) syncGeneralSettings(o *origin, rs *types.Status, replica client
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *worker) syncConfigs(o *origin, rs *types.Status, replica client.Client) error {
|
func (w *worker) syncConfigs(o *origin, replica client.Client) error {
|
||||||
qlc, err := replica.QueryLogConfig()
|
qlc, err := replica.QueryLogConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -361,7 +376,7 @@ func (w *worker) syncConfigs(o *origin, rs *types.Status, replica client.Client)
|
|||||||
type origin struct {
|
type origin struct {
|
||||||
status *types.Status
|
status *types.Status
|
||||||
rewrites *types.RewriteEntries
|
rewrites *types.RewriteEntries
|
||||||
services *types.Services
|
services types.Services
|
||||||
filters *types.FilteringStatus
|
filters *types.FilteringStatus
|
||||||
clients *types.Clients
|
clients *types.Clients
|
||||||
queryLogConfig *types.QueryLogConfig
|
queryLogConfig *types.QueryLogConfig
|
||||||
|
|||||||
13
pkg/sync/sync_suite_test.go
Normal file
13
pkg/sync/sync_suite_test.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package sync_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSync(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "Sync Suite")
|
||||||
|
}
|
||||||
419
pkg/sync/sync_test.go
Normal file
419
pkg/sync/sync_test.go
Normal file
@@ -0,0 +1,419 @@
|
|||||||
|
package sync
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/bakito/adguardhome-sync/pkg/client"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
mc "github.com/bakito/adguardhome-sync/pkg/mocks/client"
|
||||||
|
"github.com/bakito/adguardhome-sync/pkg/types"
|
||||||
|
gm "github.com/golang/mock/gomock"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("Sync", func() {
|
||||||
|
var (
|
||||||
|
mockCtrl *gm.Controller
|
||||||
|
cl *mc.MockClient
|
||||||
|
w *worker
|
||||||
|
te error
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
mockCtrl = gm.NewController(GinkgoT())
|
||||||
|
cl = mc.NewMockClient(mockCtrl)
|
||||||
|
w = &worker{
|
||||||
|
createClient: func(instance types.AdGuardInstance) (client.Client, error) {
|
||||||
|
return cl, nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
te = errors.New(uuid.NewString())
|
||||||
|
})
|
||||||
|
AfterEach(func() {
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("worker", func() {
|
||||||
|
Context("syncRewrites", func() {
|
||||||
|
var (
|
||||||
|
domain string
|
||||||
|
answer string
|
||||||
|
reO types.RewriteEntries
|
||||||
|
reR types.RewriteEntries
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
domain = uuid.NewString()
|
||||||
|
answer = uuid.NewString()
|
||||||
|
reO = []types.RewriteEntry{{Domain: domain, Answer: answer}}
|
||||||
|
reR = []types.RewriteEntry{{Domain: domain, Answer: answer}}
|
||||||
|
})
|
||||||
|
It("should have no changes (empty slices)", func() {
|
||||||
|
cl.EXPECT().RewriteList().Return(&reR, nil)
|
||||||
|
cl.EXPECT().AddRewriteEntries()
|
||||||
|
cl.EXPECT().DeleteRewriteEntries()
|
||||||
|
err := w.syncRewrites(&reO, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should add one rewrite entry", func() {
|
||||||
|
reR = []types.RewriteEntry{}
|
||||||
|
cl.EXPECT().RewriteList().Return(&reR, nil)
|
||||||
|
cl.EXPECT().AddRewriteEntries(reO[0])
|
||||||
|
cl.EXPECT().DeleteRewriteEntries()
|
||||||
|
err := w.syncRewrites(&reO, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should remove one rewrite entry", func() {
|
||||||
|
reO = []types.RewriteEntry{}
|
||||||
|
cl.EXPECT().RewriteList().Return(&reR, nil)
|
||||||
|
cl.EXPECT().AddRewriteEntries()
|
||||||
|
cl.EXPECT().DeleteRewriteEntries(reR[0])
|
||||||
|
err := w.syncRewrites(&reO, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should remove one rewrite entry", func() {
|
||||||
|
reO = []types.RewriteEntry{}
|
||||||
|
cl.EXPECT().RewriteList().Return(&reR, nil)
|
||||||
|
cl.EXPECT().AddRewriteEntries()
|
||||||
|
cl.EXPECT().DeleteRewriteEntries(reR[0])
|
||||||
|
err := w.syncRewrites(&reO, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should return error when error on RewriteList()", func() {
|
||||||
|
cl.EXPECT().RewriteList().Return(nil, te)
|
||||||
|
err := w.syncRewrites(&reO, cl)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should return error when error on AddRewriteEntries()", func() {
|
||||||
|
cl.EXPECT().RewriteList().Return(&reR, nil)
|
||||||
|
cl.EXPECT().AddRewriteEntries().Return(te)
|
||||||
|
err := w.syncRewrites(&reO, cl)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should return error when error on DeleteRewriteEntries()", func() {
|
||||||
|
cl.EXPECT().RewriteList().Return(&reR, nil)
|
||||||
|
cl.EXPECT().AddRewriteEntries()
|
||||||
|
cl.EXPECT().DeleteRewriteEntries().Return(te)
|
||||||
|
err := w.syncRewrites(&reO, cl)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Context("syncClients", func() {
|
||||||
|
var (
|
||||||
|
clO *types.Clients
|
||||||
|
clR *types.Clients
|
||||||
|
name string
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
name = uuid.NewString()
|
||||||
|
clO = &types.Clients{Clients: []types.Client{{Name: name}}}
|
||||||
|
clR = &types.Clients{Clients: []types.Client{{Name: name}}}
|
||||||
|
})
|
||||||
|
It("should have no changes (empty slices)", func() {
|
||||||
|
cl.EXPECT().Clients().Return(clR, nil)
|
||||||
|
cl.EXPECT().AddClients()
|
||||||
|
cl.EXPECT().UpdateClients()
|
||||||
|
cl.EXPECT().DeleteClients()
|
||||||
|
err := w.syncClients(clO, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should add one client", func() {
|
||||||
|
clR.Clients = []types.Client{}
|
||||||
|
cl.EXPECT().Clients().Return(clR, nil)
|
||||||
|
cl.EXPECT().AddClients(clO.Clients[0])
|
||||||
|
cl.EXPECT().UpdateClients()
|
||||||
|
cl.EXPECT().DeleteClients()
|
||||||
|
err := w.syncClients(clO, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should update one client", func() {
|
||||||
|
clR.Clients[0].Disallowed = true
|
||||||
|
cl.EXPECT().Clients().Return(clR, nil)
|
||||||
|
cl.EXPECT().AddClients()
|
||||||
|
cl.EXPECT().UpdateClients(clO.Clients[0])
|
||||||
|
cl.EXPECT().DeleteClients()
|
||||||
|
err := w.syncClients(clO, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should delete one client", func() {
|
||||||
|
clO.Clients = []types.Client{}
|
||||||
|
cl.EXPECT().Clients().Return(clR, nil)
|
||||||
|
cl.EXPECT().AddClients()
|
||||||
|
cl.EXPECT().UpdateClients()
|
||||||
|
cl.EXPECT().DeleteClients(clR.Clients[0])
|
||||||
|
err := w.syncClients(clO, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should return error when error on Clients()", func() {
|
||||||
|
cl.EXPECT().Clients().Return(nil, te)
|
||||||
|
err := w.syncClients(clO, cl)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should return error when error on AddClients()", func() {
|
||||||
|
cl.EXPECT().Clients().Return(clR, nil)
|
||||||
|
cl.EXPECT().AddClients().Return(te)
|
||||||
|
err := w.syncClients(clO, cl)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should return error when error on UpdateClients()", func() {
|
||||||
|
cl.EXPECT().Clients().Return(clR, nil)
|
||||||
|
cl.EXPECT().AddClients()
|
||||||
|
cl.EXPECT().UpdateClients().Return(te)
|
||||||
|
err := w.syncClients(clO, cl)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should return error when error on DeleteClients()", func() {
|
||||||
|
cl.EXPECT().Clients().Return(clR, nil)
|
||||||
|
cl.EXPECT().AddClients()
|
||||||
|
cl.EXPECT().UpdateClients()
|
||||||
|
cl.EXPECT().DeleteClients().Return(te)
|
||||||
|
err := w.syncClients(clO, cl)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Context("syncGeneralSettings", func() {
|
||||||
|
var (
|
||||||
|
o *origin
|
||||||
|
rs *types.Status
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
o = &origin{
|
||||||
|
status: &types.Status{},
|
||||||
|
}
|
||||||
|
rs = &types.Status{}
|
||||||
|
})
|
||||||
|
It("should have no changes", func() {
|
||||||
|
cl.EXPECT().Parental()
|
||||||
|
cl.EXPECT().SafeSearch()
|
||||||
|
cl.EXPECT().SafeBrowsing()
|
||||||
|
err := w.syncGeneralSettings(o, rs, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have protection enabled changes", func() {
|
||||||
|
o.status.ProtectionEnabled = true
|
||||||
|
cl.EXPECT().ToggleProtection(true)
|
||||||
|
cl.EXPECT().Parental()
|
||||||
|
cl.EXPECT().SafeSearch()
|
||||||
|
cl.EXPECT().SafeBrowsing()
|
||||||
|
err := w.syncGeneralSettings(o, rs, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have parental enabled changes", func() {
|
||||||
|
o.parental = true
|
||||||
|
cl.EXPECT().Parental()
|
||||||
|
cl.EXPECT().ToggleParental(true)
|
||||||
|
cl.EXPECT().SafeSearch()
|
||||||
|
cl.EXPECT().SafeBrowsing()
|
||||||
|
err := w.syncGeneralSettings(o, rs, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have safeSearch enabled changes", func() {
|
||||||
|
o.safeSearch = true
|
||||||
|
cl.EXPECT().Parental()
|
||||||
|
cl.EXPECT().SafeSearch()
|
||||||
|
cl.EXPECT().ToggleSafeSearch(true)
|
||||||
|
cl.EXPECT().SafeBrowsing()
|
||||||
|
err := w.syncGeneralSettings(o, rs, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have safeBrowsing enabled changes", func() {
|
||||||
|
o.safeBrowsing = true
|
||||||
|
cl.EXPECT().Parental()
|
||||||
|
cl.EXPECT().SafeSearch()
|
||||||
|
cl.EXPECT().SafeBrowsing()
|
||||||
|
cl.EXPECT().ToggleSafeBrowsing(true)
|
||||||
|
err := w.syncGeneralSettings(o, rs, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Context("syncConfigs", func() {
|
||||||
|
var (
|
||||||
|
o *origin
|
||||||
|
qlc *types.QueryLogConfig
|
||||||
|
sc *types.IntervalConfig
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
o = &origin{
|
||||||
|
queryLogConfig: &types.QueryLogConfig{},
|
||||||
|
statsConfig: &types.IntervalConfig{},
|
||||||
|
}
|
||||||
|
qlc = &types.QueryLogConfig{}
|
||||||
|
sc = &types.IntervalConfig{}
|
||||||
|
})
|
||||||
|
It("should have no changes", func() {
|
||||||
|
cl.EXPECT().QueryLogConfig().Return(qlc, nil)
|
||||||
|
cl.EXPECT().StatsConfig().Return(sc, nil)
|
||||||
|
err := w.syncConfigs(o, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have QueryLogConfig changes", func() {
|
||||||
|
o.queryLogConfig.Interval = 123
|
||||||
|
cl.EXPECT().QueryLogConfig().Return(qlc, nil)
|
||||||
|
cl.EXPECT().SetQueryLogConfig(false, 123, false)
|
||||||
|
cl.EXPECT().StatsConfig().Return(sc, nil)
|
||||||
|
err := w.syncConfigs(o, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have StatsConfig changes", func() {
|
||||||
|
o.statsConfig.Interval = 123
|
||||||
|
cl.EXPECT().QueryLogConfig().Return(qlc, nil)
|
||||||
|
cl.EXPECT().StatsConfig().Return(sc, nil)
|
||||||
|
cl.EXPECT().SetStatsConfig(123)
|
||||||
|
err := w.syncConfigs(o, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Context("statusWithSetup", func() {
|
||||||
|
var (
|
||||||
|
status *types.Status
|
||||||
|
inst types.AdGuardInstance
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
status = &types.Status{}
|
||||||
|
inst = types.AdGuardInstance{
|
||||||
|
AutoSetup: true,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
It("should get the replica status", func() {
|
||||||
|
cl.EXPECT().Status().Return(status, nil)
|
||||||
|
st, err := w.statusWithSetup(l, inst, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(st).Should(Equal(status))
|
||||||
|
})
|
||||||
|
It("should runs setup before getting replica status", func() {
|
||||||
|
cl.EXPECT().Status().Return(nil, client.SetupNeededError)
|
||||||
|
cl.EXPECT().Setup()
|
||||||
|
cl.EXPECT().Status().Return(status, nil)
|
||||||
|
st, err := w.statusWithSetup(l, inst, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
Ω(st).Should(Equal(status))
|
||||||
|
})
|
||||||
|
It("should fail on setup", func() {
|
||||||
|
cl.EXPECT().Status().Return(nil, client.SetupNeededError)
|
||||||
|
cl.EXPECT().Setup().Return(te)
|
||||||
|
st, err := w.statusWithSetup(l, inst, cl)
|
||||||
|
Ω(err).Should(HaveOccurred())
|
||||||
|
Ω(st).Should(BeNil())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Context("syncServices", func() {
|
||||||
|
var (
|
||||||
|
os types.Services
|
||||||
|
rs types.Services
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
os = []string{"foo"}
|
||||||
|
rs = []string{"foo"}
|
||||||
|
})
|
||||||
|
It("should have no changes", func() {
|
||||||
|
cl.EXPECT().Services().Return(rs, nil)
|
||||||
|
err := w.syncServices(os, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have services changes", func() {
|
||||||
|
os = []string{"bar"}
|
||||||
|
cl.EXPECT().Services().Return(rs, nil)
|
||||||
|
cl.EXPECT().SetServices(os)
|
||||||
|
err := w.syncServices(os, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Context("syncFilters", func() {
|
||||||
|
var (
|
||||||
|
of *types.FilteringStatus
|
||||||
|
rf *types.FilteringStatus
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
of = &types.FilteringStatus{}
|
||||||
|
rf = &types.FilteringStatus{}
|
||||||
|
})
|
||||||
|
It("should have no changes", func() {
|
||||||
|
cl.EXPECT().Filtering().Return(rf, nil)
|
||||||
|
cl.EXPECT().AddFilters(false)
|
||||||
|
cl.EXPECT().UpdateFilters(false)
|
||||||
|
cl.EXPECT().DeleteFilters(false)
|
||||||
|
cl.EXPECT().AddFilters(true)
|
||||||
|
cl.EXPECT().UpdateFilters(true)
|
||||||
|
cl.EXPECT().DeleteFilters(true)
|
||||||
|
err := w.syncFilters(of, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have changes user roles", func() {
|
||||||
|
of.UserRules = []string{"foo"}
|
||||||
|
cl.EXPECT().Filtering().Return(rf, nil)
|
||||||
|
cl.EXPECT().AddFilters(false)
|
||||||
|
cl.EXPECT().UpdateFilters(false)
|
||||||
|
cl.EXPECT().DeleteFilters(false)
|
||||||
|
cl.EXPECT().AddFilters(true)
|
||||||
|
cl.EXPECT().UpdateFilters(true)
|
||||||
|
cl.EXPECT().DeleteFilters(true)
|
||||||
|
cl.EXPECT().SetCustomRules(of.UserRules)
|
||||||
|
err := w.syncFilters(of, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
It("should have changed filtering config", func() {
|
||||||
|
of.Enabled = true
|
||||||
|
of.Interval = 123
|
||||||
|
cl.EXPECT().Filtering().Return(rf, nil)
|
||||||
|
cl.EXPECT().AddFilters(false)
|
||||||
|
cl.EXPECT().UpdateFilters(false)
|
||||||
|
cl.EXPECT().DeleteFilters(false)
|
||||||
|
cl.EXPECT().AddFilters(true)
|
||||||
|
cl.EXPECT().UpdateFilters(true)
|
||||||
|
cl.EXPECT().DeleteFilters(true)
|
||||||
|
cl.EXPECT().ToggleFiltering(of.Enabled, of.Interval)
|
||||||
|
err := w.syncFilters(of, cl)
|
||||||
|
Ω(err).ShouldNot(HaveOccurred())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
Context("sync", func() {
|
||||||
|
|
||||||
|
It("should have no changes", func() {
|
||||||
|
w.cfg = &types.Config{
|
||||||
|
Origin: types.AdGuardInstance{},
|
||||||
|
Replica: types.AdGuardInstance{URL: "foo"},
|
||||||
|
}
|
||||||
|
// origin
|
||||||
|
cl.EXPECT().Host()
|
||||||
|
cl.EXPECT().Status().Return(&types.Status{}, nil)
|
||||||
|
cl.EXPECT().Parental()
|
||||||
|
cl.EXPECT().SafeSearch()
|
||||||
|
cl.EXPECT().SafeBrowsing()
|
||||||
|
cl.EXPECT().RewriteList().Return(&types.RewriteEntries{}, nil)
|
||||||
|
cl.EXPECT().Services()
|
||||||
|
cl.EXPECT().Filtering().Return(&types.FilteringStatus{}, nil)
|
||||||
|
cl.EXPECT().Clients().Return(&types.Clients{}, nil)
|
||||||
|
cl.EXPECT().QueryLogConfig().Return(&types.QueryLogConfig{}, nil)
|
||||||
|
cl.EXPECT().StatsConfig().Return(&types.IntervalConfig{}, nil)
|
||||||
|
|
||||||
|
// replica
|
||||||
|
cl.EXPECT().Host()
|
||||||
|
cl.EXPECT().Status().Return(&types.Status{}, nil)
|
||||||
|
cl.EXPECT().Parental()
|
||||||
|
cl.EXPECT().SafeSearch()
|
||||||
|
cl.EXPECT().SafeBrowsing()
|
||||||
|
cl.EXPECT().QueryLogConfig().Return(&types.QueryLogConfig{}, nil)
|
||||||
|
cl.EXPECT().StatsConfig().Return(&types.IntervalConfig{}, nil)
|
||||||
|
cl.EXPECT().RewriteList().Return(&types.RewriteEntries{}, nil)
|
||||||
|
cl.EXPECT().AddRewriteEntries()
|
||||||
|
cl.EXPECT().DeleteRewriteEntries()
|
||||||
|
cl.EXPECT().Filtering().Return(&types.FilteringStatus{}, nil)
|
||||||
|
cl.EXPECT().AddFilters(false)
|
||||||
|
cl.EXPECT().UpdateFilters(false)
|
||||||
|
cl.EXPECT().DeleteFilters(false)
|
||||||
|
cl.EXPECT().AddFilters(true)
|
||||||
|
cl.EXPECT().UpdateFilters(true)
|
||||||
|
cl.EXPECT().DeleteFilters(true)
|
||||||
|
cl.EXPECT().Services()
|
||||||
|
cl.EXPECT().Clients().Return(&types.Clients{}, nil)
|
||||||
|
cl.EXPECT().AddClients()
|
||||||
|
cl.EXPECT().UpdateClients()
|
||||||
|
cl.EXPECT().DeleteClients()
|
||||||
|
w.sync()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -13,11 +13,12 @@ const (
|
|||||||
|
|
||||||
// Config application configuration struct
|
// Config application configuration struct
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Origin AdGuardInstance `json:"origin" yaml:"origin"`
|
Origin AdGuardInstance `json:"origin" yaml:"origin"`
|
||||||
Replica AdGuardInstance `json:"replica,omitempty" yaml:"replica,omitempty"`
|
Replica AdGuardInstance `json:"replica,omitempty" yaml:"replica,omitempty"`
|
||||||
Replicas []AdGuardInstance `json:"replicas,omitempty" yaml:"replicas,omitempty"`
|
Replicas []AdGuardInstance `json:"replicas,omitempty" yaml:"replicas,omitempty"`
|
||||||
Cron string `json:"cron,omitempty" yaml:"cron,omitempty"`
|
Cron string `json:"cron,omitempty" yaml:"cron,omitempty"`
|
||||||
API API `json:"api,omitempty" yaml:"api,omitempty"`
|
RunOnStart bool `json:"runOnStart,omitempty" yaml:"runOnStart,omitempty"`
|
||||||
|
API API `json:"api,omitempty" yaml:"api,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// API configuration
|
// API configuration
|
||||||
@@ -49,13 +50,14 @@ func (cfg *Config) UniqueReplicas() []AdGuardInstance {
|
|||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// AdGuardInstance adguard home config instance
|
// AdGuardInstance AdguardHome config instance
|
||||||
type AdGuardInstance struct {
|
type AdGuardInstance struct {
|
||||||
URL string `json:"url" yaml:"url"`
|
URL string `json:"url" yaml:"url"`
|
||||||
APIPath string `json:"apiPath,omitempty" yaml:"apiPath,omitempty"`
|
APIPath string `json:"apiPath,omitempty" yaml:"apiPath,omitempty"`
|
||||||
Username string `json:"username,omitempty" yaml:"username,omitempty"`
|
Username string `json:"username,omitempty" yaml:"username,omitempty"`
|
||||||
Password string `json:"password,omitempty" yaml:"password,omitempty"`
|
Password string `json:"password,omitempty" yaml:"password,omitempty"`
|
||||||
InsecureSkipVerify bool `json:"insecureSkipVerify" yaml:"insecureSkipVerify"`
|
InsecureSkipVerify bool `json:"insecureSkipVerify" yaml:"insecureSkipVerify"`
|
||||||
|
AutoSetup bool `json:"autoSetup" yaml:"autoSetup"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key AdGuardInstance key
|
// Key AdGuardInstance key
|
||||||
@@ -122,6 +124,35 @@ func (re *RewriteEntry) Key() string {
|
|||||||
// Filters list of Filter
|
// Filters list of Filter
|
||||||
type Filters []Filter
|
type Filters []Filter
|
||||||
|
|
||||||
|
// Merge merge Filters
|
||||||
|
func (f Filters) Merge(other Filters) (Filters, Filters, Filters) {
|
||||||
|
current := make(map[string]Filter)
|
||||||
|
|
||||||
|
var adds Filters
|
||||||
|
var updates Filters
|
||||||
|
var removes Filters
|
||||||
|
for _, f := range f {
|
||||||
|
current[f.URL] = f
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rr := range other {
|
||||||
|
if c, ok := current[rr.URL]; ok {
|
||||||
|
if !c.Equals(&rr) {
|
||||||
|
updates = append(updates, rr)
|
||||||
|
}
|
||||||
|
delete(current, rr.URL)
|
||||||
|
} else {
|
||||||
|
adds = append(adds, rr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rr := range current {
|
||||||
|
removes = append(removes, rr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return adds, updates, removes
|
||||||
|
}
|
||||||
|
|
||||||
// Filter API struct
|
// Filter API struct
|
||||||
type Filter struct {
|
type Filter struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
@@ -193,35 +224,6 @@ type RefreshFilter struct {
|
|||||||
Whitelist bool `json:"whitelist"`
|
Whitelist bool `json:"whitelist"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Merge merge RefreshFilters
|
|
||||||
func (fs *Filters) Merge(other Filters) (Filters, Filters, Filters) {
|
|
||||||
current := make(map[string]Filter)
|
|
||||||
|
|
||||||
var adds Filters
|
|
||||||
var updates Filters
|
|
||||||
var removes Filters
|
|
||||||
for _, f := range *fs {
|
|
||||||
current[f.URL] = f
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, rr := range other {
|
|
||||||
if c, ok := current[rr.URL]; ok {
|
|
||||||
if !c.Equals(&rr) {
|
|
||||||
updates = append(updates, rr)
|
|
||||||
}
|
|
||||||
delete(current, rr.URL)
|
|
||||||
} else {
|
|
||||||
adds = append(adds, rr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, rr := range current {
|
|
||||||
removes = append(removes, rr)
|
|
||||||
}
|
|
||||||
|
|
||||||
return adds, updates, removes
|
|
||||||
}
|
|
||||||
|
|
||||||
// Services API struct
|
// Services API struct
|
||||||
type Services []string
|
type Services []string
|
||||||
|
|
||||||
@@ -231,10 +233,10 @@ func (s Services) Sort() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Equals Services equal check
|
// Equals Services equal check
|
||||||
func (s *Services) Equals(o *Services) bool {
|
func (s Services) Equals(o Services) bool {
|
||||||
s.Sort()
|
s.Sort()
|
||||||
o.Sort()
|
o.Sort()
|
||||||
return equals(*s, *o)
|
return equals(s, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clients API struct
|
// Clients API struct
|
||||||
@@ -252,10 +254,10 @@ type Clients struct {
|
|||||||
|
|
||||||
// Client API struct
|
// Client API struct
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Ids []string `json:"ids"`
|
Ids []string `json:"ids,omitempty"`
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags,omitempty"`
|
||||||
BlockedServices []string `json:"blocked_services"`
|
BlockedServices []string `json:"blocked_services,omitempty"`
|
||||||
Upstreams []string `json:"upstreams"`
|
Upstreams []string `json:"upstreams,omitempty"`
|
||||||
|
|
||||||
UseGlobalSettings bool `json:"use_global_settings"`
|
UseGlobalSettings bool `json:"use_global_settings"`
|
||||||
UseGlobalBlockedServices bool `json:"use_global_blocked_services"`
|
UseGlobalBlockedServices bool `json:"use_global_blocked_services"`
|
||||||
@@ -337,3 +339,19 @@ func equals(a []string, b []string) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InstallConfig AdguardHome install config
|
||||||
|
type InstallConfig struct {
|
||||||
|
Web InstallPort `json:"web"`
|
||||||
|
DNS InstallPort `json:"dns"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// InstallPort AdguardHome install config port
|
||||||
|
type InstallPort struct {
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
CanAutofix bool `json:"can_autofix"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ var _ = Describe("Types", func() {
|
|||||||
apiPath string
|
apiPath string
|
||||||
)
|
)
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
url = "http://" + uuid.NewString()
|
url = "https://" + uuid.NewString()
|
||||||
apiPath = "/" + uuid.NewString()
|
apiPath = "/" + uuid.NewString()
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -86,6 +86,15 @@ var _ = Describe("Types", func() {
|
|||||||
|
|
||||||
Ω(u[0].Name).Should(Equal(name1))
|
Ω(u[0].Name).Should(Equal(name1))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should have no changes", func() {
|
||||||
|
originFilters = append(originFilters, types.Filter{URL: url})
|
||||||
|
replicaFilters = append(replicaFilters, types.Filter{URL: url})
|
||||||
|
a, u, d := replicaFilters.Merge(originFilters)
|
||||||
|
Ω(a).Should(BeEmpty())
|
||||||
|
Ω(u).Should(BeEmpty())
|
||||||
|
Ω(d).Should(BeEmpty())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
Context("AdGuardInstance", func() {
|
Context("AdGuardInstance", func() {
|
||||||
@@ -102,6 +111,42 @@ var _ = Describe("Types", func() {
|
|||||||
Ω(re.Key()).Should(Equal(domain + "#" + answer))
|
Ω(re.Key()).Should(Equal(domain + "#" + answer))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Context("QueryLogConfig", func() {
|
||||||
|
Context("Equal", func() {
|
||||||
|
var (
|
||||||
|
a *types.QueryLogConfig
|
||||||
|
b *types.QueryLogConfig
|
||||||
|
)
|
||||||
|
BeforeEach(func() {
|
||||||
|
a = &types.QueryLogConfig{}
|
||||||
|
b = &types.QueryLogConfig{}
|
||||||
|
})
|
||||||
|
It("should be equal", func() {
|
||||||
|
a.Enabled = true
|
||||||
|
a.Interval = 1
|
||||||
|
a.AnonymizeClientIP = true
|
||||||
|
b.Enabled = true
|
||||||
|
b.Interval = 1
|
||||||
|
b.AnonymizeClientIP = true
|
||||||
|
Ω(a.Equals(b)).Should(BeTrue())
|
||||||
|
})
|
||||||
|
It("should not be equal when enabled differs", func() {
|
||||||
|
a.Enabled = true
|
||||||
|
b.Enabled = false
|
||||||
|
Ω(a.Equals(b)).ShouldNot(BeTrue())
|
||||||
|
})
|
||||||
|
It("should not be equal when interval differs", func() {
|
||||||
|
a.Interval = 1
|
||||||
|
b.Interval = 2
|
||||||
|
Ω(a.Equals(b)).ShouldNot(BeTrue())
|
||||||
|
})
|
||||||
|
It("should not be equal when anonymizeClientIP differs", func() {
|
||||||
|
a.AnonymizeClientIP = true
|
||||||
|
b.AnonymizeClientIP = false
|
||||||
|
Ω(a.Equals(b)).ShouldNot(BeTrue())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Context("RewriteEntries", func() {
|
Context("RewriteEntries", func() {
|
||||||
Context("Merge", func() {
|
Context("Merge", func() {
|
||||||
var (
|
var (
|
||||||
@@ -132,6 +177,14 @@ var _ = Describe("Types", func() {
|
|||||||
|
|
||||||
Ω(d[0].Domain).Should(Equal(domain))
|
Ω(d[0].Domain).Should(Equal(domain))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("should have no changes", func() {
|
||||||
|
originRE = append(originRE, types.RewriteEntry{Domain: domain})
|
||||||
|
replicaRE = append(replicaRE, types.RewriteEntry{Domain: domain})
|
||||||
|
a, d := replicaRE.Merge(&originRE)
|
||||||
|
Ω(a).Should(BeEmpty())
|
||||||
|
Ω(d).Should(BeEmpty())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
Context("UserRules", func() {
|
Context("UserRules", func() {
|
||||||
@@ -233,4 +286,23 @@ var _ = Describe("Types", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
Context("Services", func() {
|
||||||
|
Context("Equals", func() {
|
||||||
|
It("should be equal", func() {
|
||||||
|
s1 := types.Services([]string{"a", "b"})
|
||||||
|
s2 := types.Services([]string{"b", "a"})
|
||||||
|
Ω(s1.Equals(s2)).Should(BeTrue())
|
||||||
|
})
|
||||||
|
It("should not be equal different values", func() {
|
||||||
|
s1 := types.Services([]string{"a", "b"})
|
||||||
|
s2 := types.Services([]string{"B", "a"})
|
||||||
|
Ω(s1.Equals(s2)).ShouldNot(BeTrue())
|
||||||
|
})
|
||||||
|
It("should not be equal different length", func() {
|
||||||
|
s1 := types.Services([]string{"a", "b"})
|
||||||
|
s2 := types.Services([]string{"b", "a", "c"})
|
||||||
|
Ω(s1.Equals(s2)).ShouldNot(BeTrue())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
4
testdata/blockedservices-list.json
vendored
Normal file
4
testdata/blockedservices-list.json
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
"9gag",
|
||||||
|
"dailymotion"
|
||||||
|
]
|
||||||
81
testdata/clients.json
vendored
Normal file
81
testdata/clients.json
vendored
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"ids": [
|
||||||
|
"192.168.1.3"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"device_pc"
|
||||||
|
],
|
||||||
|
"name": "PC",
|
||||||
|
"use_global_settings": true,
|
||||||
|
"filtering_enabled": false,
|
||||||
|
"parental_enabled": false,
|
||||||
|
"safesearch_enabled": false,
|
||||||
|
"safebrowsing_enabled": false,
|
||||||
|
"use_global_blocked_services": true,
|
||||||
|
"blocked_services": null,
|
||||||
|
"upstreams": null,
|
||||||
|
"whois_info": null,
|
||||||
|
"disallowed": false,
|
||||||
|
"disallowed_rule": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ids": [
|
||||||
|
"192.168.1.2"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"device_phone"
|
||||||
|
],
|
||||||
|
"name": "Phone LAN",
|
||||||
|
"use_global_settings": true,
|
||||||
|
"filtering_enabled": false,
|
||||||
|
"parental_enabled": false,
|
||||||
|
"safesearch_enabled": false,
|
||||||
|
"safebrowsing_enabled": false,
|
||||||
|
"use_global_blocked_services": false,
|
||||||
|
"blocked_services": [
|
||||||
|
"facebook",
|
||||||
|
"ok",
|
||||||
|
"vk",
|
||||||
|
"mail_ru",
|
||||||
|
"qq"
|
||||||
|
],
|
||||||
|
"upstreams": [],
|
||||||
|
"whois_info": null,
|
||||||
|
"disallowed": false,
|
||||||
|
"disallowed_rule": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"auto_clients": [
|
||||||
|
{
|
||||||
|
"ip": "127.0.0.1",
|
||||||
|
"name": "localhost",
|
||||||
|
"source": "etc/hosts",
|
||||||
|
"whois_info": {}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"supported_tags": [
|
||||||
|
"device_audio",
|
||||||
|
"device_camera",
|
||||||
|
"device_gameconsole",
|
||||||
|
"device_laptop",
|
||||||
|
"device_nas",
|
||||||
|
"device_other",
|
||||||
|
"device_pc",
|
||||||
|
"device_phone",
|
||||||
|
"device_printer",
|
||||||
|
"device_securityalarm",
|
||||||
|
"device_tablet",
|
||||||
|
"device_tv",
|
||||||
|
"os_android",
|
||||||
|
"os_ios",
|
||||||
|
"os_linux",
|
||||||
|
"os_macos",
|
||||||
|
"os_other",
|
||||||
|
"os_windows",
|
||||||
|
"user_admin",
|
||||||
|
"user_child",
|
||||||
|
"user_regular"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
testdata/parental-status.json
vendored
Normal file
3
testdata/parental-status.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
5
testdata/querylog_info.json
vendored
Normal file
5
testdata/querylog_info.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"enabled": true,
|
||||||
|
"interval": 90,
|
||||||
|
"anonymize_client_ip": false
|
||||||
|
}
|
||||||
10
testdata/rewrite-list.json
vendored
Normal file
10
testdata/rewrite-list.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"domain": "foo.com",
|
||||||
|
"answer": "192.168.1.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "bar.com",
|
||||||
|
"answer": "192.168.1.12"
|
||||||
|
}
|
||||||
|
]
|
||||||
3
testdata/safebrowsing-status.json
vendored
Normal file
3
testdata/safebrowsing-status.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
3
testdata/safesearch-status.json
vendored
Normal file
3
testdata/safesearch-status.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
3
testdata/stats_info.json
vendored
Normal file
3
testdata/stats_info.json
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"interval": 1
|
||||||
|
}
|
||||||
12
testdata/status.json
vendored
Normal file
12
testdata/status.json
vendored
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"dns_addresses": [
|
||||||
|
"192.168.1.2"
|
||||||
|
],
|
||||||
|
"dns_port": 53,
|
||||||
|
"http_port": 45158,
|
||||||
|
"protection_enabled": true,
|
||||||
|
"dhcp_available": true,
|
||||||
|
"running": true,
|
||||||
|
"version": "v0.105.2",
|
||||||
|
"language": "en"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user