Compare commits

...

3 Commits

Author SHA1 Message Date
Marc Brugger
5fca3b1002 better readable env vars (#270)
* better readable env vars
2024-01-08 19:39:47 +01:00
bakito
1edf5ae52a add filter test cases 2024-01-08 19:20:31 +01:00
bakito
39f7f41e6d update readme 2024-01-07 22:44:32 +01:00
9 changed files with 311 additions and 158 deletions

View File

@@ -146,7 +146,7 @@ services:
environment:
LOG_LEVEL: "info"
ORIGIN_URL: "https://192.168.1.2:3000"
# ORIGIN_WEBURL: "https://some-other.url" # used in the web interface (default: <origin-url>
# ORIGIN_WEB_URL: "https://some-other.url" # used in the web interface (default: <origin-url>
ORIGIN_USERNAME: "username"
ORIGIN_PASSWORD: "password"
@@ -156,29 +156,29 @@ services:
REPLICA1_URL: "http://192.168.1.4"
REPLICA1_USERNAME: "username"
REPLICA1_PASSWORD: "password"
REPLICA1_APIPATH: "/some/path/control"
# REPLICA1_WEBURL: "https://some-other.url" # used in the web interface (default: <replica-url>
# REPLICA1_AUTOSETUP: true # if true, AdGuardHome is automatically initialized.
# REPLICA1_INTERFACENAME: 'ens18' # use custom dhcp interface name
# REPLICA1_DHCPSERVERENABLED: true/false (optional) enables/disables the dhcp server on the replica
REPLICA1_API_PATH: "/some/path/control"
# REPLICA1_WEB_URL: "https://some-other.url" # used in the web interface (default: <replica-url>
# REPLICA1_AUTO_SETUP: true # if true, AdGuardHome is automatically initialized.
# REPLICA1_INTERFACE_NAME: 'ens18' # use custom dhcp interface name
# REPLICA1_DHCP_SERVER_ENABLED: true/false (optional) enables/disables the dhcp server on the replica
CRON: "*/10 * * * *" # run every 10 minutes
RUNONSTART: true
# CONTINUEONERROR: false # If enabled, the synchronisation task will not fail on single errors, but will log the errors and continue
# CONTINUE_ON_ERROR: false # If enabled, the synchronisation task will not fail on single errors, but will log the errors and continue
# Configure the sync API server, disabled if api port is 0
API_PORT: 8080
# Configure sync features; by default all features are enabled.
# FEATURES_GENERALSETTINGS: true
# FEATURES_QUERYLOGCONFIG: true
# FEATURES_STATSCONFIG: true
# FEATURES_CLIENTSETTINGS: true
# FEATURES_GENERAL_SETTINGS: true
# FEATURES_QUERY_LOG_CONFIG: true
# FEATURES_STATS_CONFIG: true
# FEATURES_CLIENT_SETTINGS: true
# FEATURES_SERVICES: true
# FEATURES_FILTERS: true
# FEATURES_DHCP_SERVERCONFIG: true
# FEATURES_DHCP_STATICLEASES: true
# FEATURES_DNS_SERVERCONFIG: true
# FEATURES_DNS_ACCESSLISTS: true
# FEATURES_DHCP_SERVER_CONFIG: true
# FEATURES_DHCP_STATIC_LEASES: true
# FEATURES_DNS_SERVER_CONFIG: true
# FEATURES_DNS_ACCESS_LISTS: true
# FEATURES_DNS_REWRITES: true
ports:
- 8080:8080

View File

@@ -4,10 +4,12 @@ import (
"fmt"
"os"
"regexp"
"strconv"
"strings"
"github.com/bakito/adguardhome-sync/pkg/log"
"github.com/bakito/adguardhome-sync/pkg/types"
"github.com/bakito/adguardhome-sync/pkg/utils"
"github.com/bakito/adguardhome-sync/version"
"github.com/mitchellh/go-homedir"
"github.com/spf13/cobra"
@@ -15,56 +17,45 @@ import (
)
const (
configCron = "cron"
configRunOnStart = "runOnStart"
configCron = "CRON"
configRunOnStart = "RUN_ON_START"
configPrintConfigOnly = "PRINT_CONFIG_ONLY"
configContinueOnError = "CONTINUE_ON_ERROR"
configLogLevel = "LOG_LEVEL"
configAPIPort = "api.port"
configAPIUsername = "api.username"
configAPIPassword = "api.password"
configAPIDarkMode = "api.darkMode"
configAPIPort = "API.PORT"
configAPIUsername = "API.USERNAME"
configAPIPassword = "API.PASSWORD"
configAPIDarkMode = "API.DARK_MODE"
configFeatureDHCPServerConfig = "features.dhcp.serverConfig"
configFeatureDHCPStaticLeases = "features.dhcp.staticLeases"
configFeatureDNServerConfig = "features.dns.serverConfig"
configFeatureDNSPAccessLists = "features.dns.accessLists"
configFeatureDNSRewrites = "features.dns.rewrites"
configFeatureGeneralSettings = "features.generalSettings"
configFeatureQueryLogConfig = "features.queryLogConfig"
configFeatureStatsConfig = "features.statsConfig"
configFeatureClientSettings = "features.clientSettings"
configFeatureServices = "features.services"
configFeatureFilters = "features.filters"
configFeatureDHCPServerConfig = "FEATURES.DHCP.SERVER_CONFIG"
configFeatureDHCPStaticLeases = "FEATURES.DHCP.STATIC_LEASES"
configFeatureDNServerConfig = "FEATURES.DNS.SERVER_CONFIG"
configFeatureDNSPAccessLists = "FEATURES.DNS.ACCESS_LISTS"
configFeatureDNSRewrites = "FEATURES.DNS.rewrites"
configFeatureGeneralSettings = "FEATURES.GENERAL_SETTINGS"
configFeatureQueryLogConfig = "FEATURES.QUERY_LOG_CONFIG"
configFeatureStatsConfig = "FEATURES.STATS_CONFIG"
configFeatureClientSettings = "FEATURES.CLIENT_SETTINGS"
configFeatureServices = "FEATURES.SERVICES"
configFeatureFilters = "FEATURES.FILTERS"
configOriginURL = "origin.url"
configOriginWebURL = "origin.webURL"
configOriginAPIPath = "origin.apiPath"
configOriginUsername = "origin.username"
configOriginPassword = "origin.password"
configOriginCookie = "origin.cookie"
configOriginInsecureSkipVerify = "origin.insecureSkipVerify"
configOriginURL = "ORIGIN.URL"
configOriginWebURL = "ORIGIN.WEB_URL"
configOriginAPIPath = "ORIGIN.API_PATH"
configOriginUsername = "ORIGIN.USERNAME"
configOriginPassword = "ORIGIN.PASSWORD"
configOriginCookie = "ORIGIN.COOKIE"
configOriginInsecureSkipVerify = "ORIGIN.INSECURE_SKIP_VERIFY"
configReplicaURL = "replica.url"
configReplicaWebURL = "replica.webURL"
configReplicaAPIPath = "replica.apiPath"
configReplicaUsername = "replica.username"
configReplicaPassword = "replica.password"
configReplicaCookie = "replica.cookie"
configReplicaInsecureSkipVerify = "replica.insecureSkipVerify"
configReplicaAutoSetup = "replica.autoSetup"
configReplicaInterfaceName = "replica.interfaceName"
envReplicasUsernameFormat = "REPLICA%s_USERNAME" // #nosec G101
envReplicasPasswordFormat = "REPLICA%s_PASSWORD" // #nosec G101
envReplicasCookieFormat = "REPLICA%s_COOKIE" // #nosec G101
envReplicasAPIPathFormat = "REPLICA%s_APIPATH"
envReplicasInsecureSkipVerifyFormat = "REPLICA%s_INSECURESKIPVERIFY"
envReplicasAutoSetup = "REPLICA%s_AUTOSETUP"
envReplicasInterfaceName = "REPLICA%s_INTERFACENAME"
envDHCPServerEnabled = "REPLICA%s_DHCPSERVERENABLED"
envWebURL = "REPLICA%s_WEBURL"
configReplicaURL = "REPLICA.URL"
configReplicaWebURL = "REPLICA.WEB_URL"
configReplicaAPIPath = "REPLICA.API_PATH"
configReplicaUsername = "REPLICA.USERNAME"
configReplicaPassword = "REPLICA.PASSWORD"
configReplicaCookie = "REPLICA.COOKIE"
configReplicaInsecureSkipVerify = "REPLICA.INSECURE_SKIP_VERIFY"
configReplicaAutoSetup = "REPLICA.AUTO_SETUP"
configReplicaInterfaceName = "REPLICA.INTERFACE_NAME"
)
var (
@@ -147,33 +138,116 @@ func getConfig() (*types.Config, error) {
cfg.Replicas = append(cfg.Replicas, collectEnvReplicas()...)
}
handleDeprecatedEnvVars(cfg)
return cfg, nil
}
func handleDeprecatedEnvVars(cfg *types.Config) {
value := checkDeprecatedEnvVar("RUNONSTART", "RUN_ON_START")
if value != "" {
cfg.RunOnStart, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("API_DARKMODE", "API_DARK_MODE")
if value != "" {
cfg.API.DarkMode, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("FEATURES_GENERALSETTINGS", "FEATURES_GENERAL_SETTINGS")
if value != "" {
cfg.Features.GeneralSettings, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("FEATURES_QUERYLOGCONFIG", "FEATURES_QUERY_LOG_CONFIG")
if value != "" {
cfg.Features.QueryLogConfig, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("FEATURES_STATSCONFIG", "FEATURES_STATS_CONFIG")
if value != "" {
cfg.Features.StatsConfig, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("FEATURES_CLIENTSETTINGS", "FEATURES_CLIENT_SETTINGS")
if value != "" {
cfg.Features.ClientSettings, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("FEATURES_DHCP_SERVERCONFIG", "FEATURES_DHCP_SERVER_CONFIG")
if value != "" {
cfg.Features.DHCP.ServerConfig, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("FEATURES_DHCP_STATICLEASES", "FEATURES_DHCP_STATIC_LEASES")
if value != "" {
cfg.Features.DHCP.StaticLeases, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("FEATURES_DNS_ACCESSLISTS", "FEATURES_DNS_ACCESS_LISTS")
if value != "" {
cfg.Features.DNS.AccessLists, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("FEATURES_DNS_SERVERCONFIG", "FEATURES_DNS_SERVER_CONFIG")
if value != "" {
cfg.Features.DNS.ServerConfig, _ = strconv.ParseBool(value)
}
if cfg.Replica != nil {
value = checkDeprecatedEnvVar("REPLICA_WEBURL", "REPLICA_WEB_URL")
if value != "" {
cfg.Replica.WebURL = value
}
value = checkDeprecatedEnvVar("REPLICA_AUTOSETUP", "REPLICA_AUTO_SETUP")
if value != "" {
cfg.Replica.AutoSetup, _ = strconv.ParseBool(value)
}
value = checkDeprecatedEnvVar("REPLICA_INTERFACENAME", "REPLICA_INTERFACE_NAME")
if value != "" {
cfg.Replica.InterfaceName = value
}
value = checkDeprecatedEnvVar("REPLICA_DHCPSERVERENABLED", "REPLICA_DHCP_SERVER_ENABLED")
if value != "" {
if b, err := strconv.ParseBool(value); err != nil {
cfg.Replica.DHCPServerEnabled = utils.Ptr(b)
}
}
}
}
func checkDeprecatedEnvVar(oldName string, newName string) string {
old, oldOK := os.LookupEnv(oldName)
if oldOK {
logger.With("deprecated", oldName, "replacement", newName).
Warn("Deprecated env variable is used, please use the correct one")
}
new, newOK := os.LookupEnv(newName)
if newOK {
return new
}
return old
}
func checkDeprecatedReplicaEnvVar(oldPattern, newPattern, replicaID string) string {
return checkDeprecatedEnvVar(fmt.Sprintf(oldPattern, replicaID), fmt.Sprintf(newPattern, replicaID))
}
// Manually collect replicas from env.
func collectEnvReplicas() []types.AdGuardInstance {
var replicas []types.AdGuardInstance
for _, v := range os.Environ() {
if envReplicasURLPattern.MatchString(v) {
sm := envReplicasURLPattern.FindStringSubmatch(v)
index := sm[1]
re := types.AdGuardInstance{
URL: sm[2],
WebURL: os.Getenv(fmt.Sprintf(envWebURL, sm[1])),
Username: os.Getenv(fmt.Sprintf(envReplicasUsernameFormat, sm[1])),
Password: os.Getenv(fmt.Sprintf(envReplicasPasswordFormat, sm[1])),
Cookie: os.Getenv(fmt.Sprintf(envReplicasCookieFormat, sm[1])),
APIPath: os.Getenv(fmt.Sprintf(envReplicasAPIPathFormat, sm[1])),
InsecureSkipVerify: strings.EqualFold(os.Getenv(fmt.Sprintf(envReplicasInsecureSkipVerifyFormat, sm[1])), "true"),
AutoSetup: strings.EqualFold(os.Getenv(fmt.Sprintf(envReplicasAutoSetup, sm[1])), "true"),
InterfaceName: os.Getenv(fmt.Sprintf(envReplicasInterfaceName, sm[1])),
WebURL: os.Getenv(fmt.Sprintf("REPLICA%s_WEB_URL", index)),
APIPath: checkDeprecatedReplicaEnvVar("REPLICA%s_APIPATH", "REPLICA%s_API_PATH", index),
Username: os.Getenv(fmt.Sprintf("REPLICA%s_USERNAME", index)),
Password: os.Getenv(fmt.Sprintf("REPLICA%s_PASSWORD", index)),
Cookie: os.Getenv(fmt.Sprintf("REPLICA%s_COOKIE", index)),
InsecureSkipVerify: strings.EqualFold(checkDeprecatedReplicaEnvVar("REPLICA%s_INSECURESKIPVERIFY", "REPLICA%s_INSECURE_SKIP_VERIFY", index), "true"),
AutoSetup: strings.EqualFold(checkDeprecatedReplicaEnvVar("REPLICA%s_AUTOSETUP", "REPLICA%s_AUTO_SETUP", index), "true"),
InterfaceName: checkDeprecatedReplicaEnvVar("REPLICA%s_INTERFACENAME", "REPLICA%s_INTERFACE_NAME", index),
}
if dhcpEnabled, ok := os.LookupEnv(fmt.Sprintf(envDHCPServerEnabled, sm[1])); ok {
if strings.EqualFold(dhcpEnabled, "true") {
re.DHCPServerEnabled = boolPtr(true)
} else if strings.EqualFold(dhcpEnabled, "false") {
re.DHCPServerEnabled = boolPtr(false)
}
dhcpEnabled := checkDeprecatedReplicaEnvVar("REPLICA%s_DHCPSERVERENABLED", "REPLICA%s_DHCP_SERVER_ENABLED", index)
if strings.EqualFold(dhcpEnabled, "true") {
re.DHCPServerEnabled = utils.Ptr(true)
} else if strings.EqualFold(dhcpEnabled, "false") {
re.DHCPServerEnabled = utils.Ptr(false)
}
if re.APIPath == "" {
re.APIPath = "/control"
@@ -184,7 +258,3 @@ func collectEnvReplicas() []types.AdGuardInstance {
return replicas
}
func boolPtr(b bool) *bool {
return &b
}

View File

@@ -10,6 +10,22 @@ import (
)
var envVars = []string{
"FEATURES_GENERAL_SETTINGS",
"FEATURES_QUERY_LOG_CONFIG",
"FEATURES_STATS_CONFIG",
"FEATURES_CLIENT_SETTINGS",
"FEATURES_SERVICES",
"FEATURES_FILTERS",
"FEATURES_DHCP_SERVER_CONFIG",
"FEATURES_DHCP_STATIC_LEASES",
"FEATURES_DNS_SERVER_CONFIG",
"FEATURES_DNS_ACCESS_LISTS",
"FEATURES_DNS_REWRITES",
"REPLICA1_INTERFACE_NAME",
"REPLICA1_DHCP_SERVER_ENABLED",
}
var deprecatedEnvVars = []string{
"FEATURES_GENERALSETTINGS",
"FEATURES_QUERYLOGCONFIG",
"FEATURES_STATSCONFIG",
@@ -26,56 +42,83 @@ var envVars = []string{
}
var _ = Describe("Run", func() {
BeforeEach(func() {
for _, envVar := range envVars {
Ω(os.Unsetenv(envVar)).ShouldNot(HaveOccurred())
}
initConfig()
})
AfterEach(func() {
for _, envVar := range envVars {
Ω(os.Unsetenv(envVar)).ShouldNot(HaveOccurred())
}
})
Context("getConfig", func() {
It("features should be true by default", func() {
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
verifyFeatures(cfg, true)
})
It("features should be false", func() {
for _, envVar := range envVars {
Context("deprecated", func() {
BeforeEach(func() {
for _, envVar := range deprecatedEnvVars {
Ω(os.Setenv(envVar, "false")).ShouldNot(HaveOccurred())
}
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
verifyFeatures(cfg, false)
initConfig()
})
Context("interface name", func() {
It("should set interface name of replica 1", func() {
Ω(os.Setenv("REPLICA1_URL", "https://foo.bar")).ShouldNot(HaveOccurred())
Ω(os.Setenv(fmt.Sprintf(envReplicasInterfaceName, "1"), "eth0")).ShouldNot(HaveOccurred())
AfterEach(func() {
for _, envVar := range deprecatedEnvVars {
Ω(os.Unsetenv(envVar)).ShouldNot(HaveOccurred())
}
})
Context("getConfig", func() {
It("features should be false", func() {
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
Ω(cfg.Replicas[0].InterfaceName).Should(Equal("eth0"))
verifyFeatures(cfg, false)
})
})
Context("dhcp server", func() {
It("should enable the dhcp server of replica 1", func() {
Ω(os.Setenv("REPLICA1_URL", "https://foo.bar")).ShouldNot(HaveOccurred())
Ω(os.Setenv(fmt.Sprintf(envDHCPServerEnabled, "1"), "true")).ShouldNot(HaveOccurred())
})
Context("current", func() {
BeforeEach(func() {
for _, envVar := range envVars {
Ω(os.Unsetenv(envVar)).ShouldNot(HaveOccurred())
}
initConfig()
})
AfterEach(func() {
for _, envVar := range envVars {
Ω(os.Unsetenv(envVar)).ShouldNot(HaveOccurred())
}
})
Context("getConfig", func() {
It("features should be true by default", func() {
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
Ω(cfg.Replicas[0].DHCPServerEnabled).ShouldNot(BeNil())
Ω(*cfg.Replicas[0].DHCPServerEnabled).Should(BeTrue())
verifyFeatures(cfg, true)
})
It("should disable the dhcp server of replica 1", func() {
Ω(os.Setenv("REPLICA1_URL", "https://foo.bar")).ShouldNot(HaveOccurred())
Ω(os.Setenv(fmt.Sprintf(envDHCPServerEnabled, "1"), "false")).ShouldNot(HaveOccurred())
It("features should be true by default", func() {
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
Ω(cfg.Replicas[0].DHCPServerEnabled).ShouldNot(BeNil())
Ω(*cfg.Replicas[0].DHCPServerEnabled).Should(BeFalse())
verifyFeatures(cfg, true)
})
It("features should be false", func() {
for _, envVar := range envVars {
Ω(os.Setenv(envVar, "false")).ShouldNot(HaveOccurred())
}
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
verifyFeatures(cfg, false)
})
Context("interface name", func() {
It("should set interface name of replica 1", func() {
Ω(os.Setenv("REPLICA1_URL", "https://foo.bar")).ShouldNot(HaveOccurred())
Ω(os.Setenv(fmt.Sprintf("REPLICA%s_INTERFACE_NAME", "1"), "eth0")).ShouldNot(HaveOccurred())
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
Ω(cfg.Replicas[0].InterfaceName).Should(Equal("eth0"))
})
})
Context("dhcp server", func() {
It("should enable the dhcp server of replica 1", func() {
Ω(os.Setenv("REPLICA1_URL", "https://foo.bar")).ShouldNot(HaveOccurred())
Ω(os.Setenv(fmt.Sprintf("REPLICA%s_DHCPSERVERENABLED", "1"), "true")).ShouldNot(HaveOccurred())
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
Ω(cfg.Replicas[0].DHCPServerEnabled).ShouldNot(BeNil())
Ω(*cfg.Replicas[0].DHCPServerEnabled).Should(BeTrue())
})
It("should disable the dhcp server of replica 1", func() {
Ω(os.Setenv("REPLICA1_URL", "https://foo.bar")).ShouldNot(HaveOccurred())
Ω(os.Setenv(fmt.Sprintf("REPLICA%s_DHCPSERVERENABLED", "1"), "false")).ShouldNot(HaveOccurred())
cfg, err := getConfig()
Ω(err).ShouldNot(HaveOccurred())
Ω(cfg.Replicas[0].DHCPServerEnabled).ShouldNot(BeNil())
Ω(*cfg.Replicas[0].DHCPServerEnabled).Should(BeFalse())
})
})
})
})

View File

@@ -54,9 +54,6 @@ func init() {
"will not fail on single errors, but will log the errors and continue.")
_ = viper.BindPFlag(configContinueOnError, doCmd.PersistentFlags().Lookup("continueOnError"))
doCmd.PersistentFlags().String("logLevel", "info", "The log level to set. One of (debug, info, warn and error)")
_ = viper.BindPFlag(configLogLevel, doCmd.PersistentFlags().Lookup("logLevel"))
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"))
doCmd.PersistentFlags().String("api-username", "", "Sync API username")
@@ -93,8 +90,8 @@ func init() {
doCmd.PersistentFlags().String("origin-url", "", "Origin instance url")
_ = viper.BindPFlag(configOriginURL, doCmd.PersistentFlags().Lookup("origin-url"))
doCmd.PersistentFlags().String("origin-weburl", "", "Origin instance web url used in the web interface (default: <origin-url>)")
_ = viper.BindPFlag(configOriginWebURL, doCmd.PersistentFlags().Lookup("origin-weburl"))
doCmd.PersistentFlags().String("origin-web-url", "", "Origin instance web url used in the web interface (default: <origin-url>)")
_ = viper.BindPFlag(configOriginWebURL, doCmd.PersistentFlags().Lookup("origin-web-url"))
doCmd.PersistentFlags().String("origin-api-path", "/control", "Origin instance API path")
_ = viper.BindPFlag(configOriginAPIPath, doCmd.PersistentFlags().Lookup("origin-api-path"))
doCmd.PersistentFlags().String("origin-username", "", "Origin instance username")
@@ -108,8 +105,8 @@ func init() {
doCmd.PersistentFlags().String("replica-url", "", "Replica instance url")
_ = viper.BindPFlag(configReplicaURL, doCmd.PersistentFlags().Lookup("replica-url"))
doCmd.PersistentFlags().String("replica-weburl", "", "Replica instance web url used in the web interface (default: <replica-url>)")
_ = viper.BindPFlag(configOriginWebURL, doCmd.PersistentFlags().Lookup("replica-weburl"))
doCmd.PersistentFlags().String("replica-web-url", "", "Replica instance web url used in the web interface (default: <replica-url>)")
_ = viper.BindPFlag(configReplicaWebURL, doCmd.PersistentFlags().Lookup("replica-web-url"))
doCmd.PersistentFlags().String("replica-api-path", "/control", "Replica instance API path")
_ = viper.BindPFlag(configReplicaAPIPath, doCmd.PersistentFlags().Lookup("replica-api-path"))
doCmd.PersistentFlags().String("replica-username", "", "Replica instance username")

2
go.mod
View File

@@ -62,7 +62,7 @@ require (
github.com/ugorji/go/codec v1.2.12 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.7.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/crypto v0.18.0 // indirect
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sys v0.16.0 // indirect

4
go.sum
View File

@@ -171,8 +171,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=

View File

@@ -425,6 +425,50 @@ var _ = Describe("Sync", func() {
err := actionFilters(ac)
Ω(err).ShouldNot(HaveOccurred())
})
It("should add a filter", func() {
ac.origin.filters.Filters = utils.Ptr([]model.Filter{{Name: "foo", Url: "https://foo.bar"}})
cl.EXPECT().Filtering().Return(rf, nil)
cl.EXPECT().AddFilter(false, model.Filter{Name: "foo", Url: "https://foo.bar"})
cl.EXPECT().RefreshFilters(gm.Any())
err := actionFilters(ac)
Ω(err).ShouldNot(HaveOccurred())
})
It("should delete a filter", func() {
rf.Filters = utils.Ptr([]model.Filter{{Name: "foo", Url: "https://foo.bar"}})
cl.EXPECT().Filtering().Return(rf, nil)
cl.EXPECT().DeleteFilter(false, model.Filter{Name: "foo", Url: "https://foo.bar"})
err := actionFilters(ac)
Ω(err).ShouldNot(HaveOccurred())
})
It("should update a filter", func() {
ac.origin.filters.Filters = utils.Ptr([]model.Filter{{Name: "foo", Url: "https://foo.bar", Enabled: true}})
rf.Filters = utils.Ptr([]model.Filter{{Name: "foo", Url: "https://foo.bar"}})
cl.EXPECT().Filtering().Return(rf, nil)
cl.EXPECT().UpdateFilter(false, model.Filter{Name: "foo", Url: "https://foo.bar", Enabled: true})
cl.EXPECT().RefreshFilters(gm.Any())
err := actionFilters(ac)
Ω(err).ShouldNot(HaveOccurred())
})
It("should abort after failed added filter", func() {
ac.continueOnError = false
ac.origin.filters.Filters = utils.Ptr([]model.Filter{{Name: "foo", Url: "https://foo.bar"}})
cl.EXPECT().Filtering().Return(rf, nil)
cl.EXPECT().AddFilter(false, model.Filter{Name: "foo", Url: "https://foo.bar"}).Return(errors.New("test failure"))
err := actionFilters(ac)
Ω(err).Should(HaveOccurred())
})
It("should continue after failed added filter", func() {
ac.continueOnError = true
ac.origin.filters.Filters = utils.Ptr([]model.Filter{{Name: "foo", Url: "https://foo.bar"}, {Name: "bar", Url: "https://bar.foo"}})
cl.EXPECT().Filtering().Return(rf, nil)
cl.EXPECT().AddFilter(false, model.Filter{Name: "foo", Url: "https://foo.bar"}).Return(errors.New("test failure"))
cl.EXPECT().AddFilter(false, model.Filter{Name: "bar", Url: "https://bar.foo"})
cl.EXPECT().RefreshFilters(gm.Any())
err := actionFilters(ac)
Ω(err).ShouldNot(HaveOccurred())
})
})
Context("actionDNSAccessLists", func() {

View File

@@ -6,26 +6,26 @@ import (
// Features feature flags
type Features struct {
DNS DNS `json:"dns" yaml:"dns"`
DHCP DHCP `json:"dhcp" yaml:"dhcp"`
GeneralSettings bool `json:"generalSettings" yaml:"generalSettings"`
QueryLogConfig bool `json:"queryLogConfig" yaml:"queryLogConfig"`
StatsConfig bool `json:"statsConfig" yaml:"statsConfig"`
ClientSettings bool `json:"clientSettings" yaml:"clientSettings"`
Services bool `json:"services" yaml:"services"`
Filters bool `json:"filters" yaml:"filters"`
DNS DNS `json:"dns" yaml:"dns" mapstructure:"DNS"`
DHCP DHCP `json:"dhcp" yaml:"dhcp" mapstructure:"DHCP"`
GeneralSettings bool `json:"generalSettings" yaml:"generalSettings" mapstructure:"GENERAL_SETTINGS"`
QueryLogConfig bool `json:"queryLogConfig" yaml:"queryLogConfig" mapstructure:"QUERY_LOG_CONFIG"`
StatsConfig bool `json:"statsConfig" yaml:"statsConfig" mapstructure:"STATS_CONFIG"`
ClientSettings bool `json:"clientSettings" yaml:"clientSettings" mapstructure:"CLIENT_SETTINGS"`
Services bool `json:"services" yaml:"services" mapstructure:"SERVICES"`
Filters bool `json:"filters" yaml:"filters" mapstructure:"FILTERS"`
}
// DHCP features
type DHCP struct {
ServerConfig bool `json:"serverConfig" yaml:"serverConfig"`
StaticLeases bool `json:"staticLeases" yaml:"staticLeases"`
ServerConfig bool `json:"serverConfig" yaml:"serverConfig" mapstructure:"SERVER_CONFIG"`
StaticLeases bool `json:"staticLeases" yaml:"staticLeases" mapstructure:"STATIC_LEASES"`
}
// DNS features
type DNS struct {
AccessLists bool `json:"accessLists" yaml:"accessLists"`
ServerConfig bool `json:"serverConfig" yaml:"serverConfig"`
AccessLists bool `json:"accessLists" yaml:"accessLists" mapstructure:"ACCESS_LISTS"`
ServerConfig bool `json:"serverConfig" yaml:"serverConfig" mapstructure:"SERVER_CONFIG"`
Rewrites bool `json:"rewrites" yaml:"rewrites"`
}

View File

@@ -15,24 +15,23 @@ const (
// Config application configuration struct
// +k8s:deepcopy-gen=true
type Config struct {
Origin AdGuardInstance `json:"origin" yaml:"origin"`
Replica *AdGuardInstance `json:"replica,omitempty" yaml:"replica,omitempty"`
Origin AdGuardInstance `json:"origin" yaml:"origin" mapstructure:"ORIGIN"`
Replica *AdGuardInstance `json:"replica,omitempty" yaml:"replica,omitempty" mapstructure:"REPLICA"`
Replicas []AdGuardInstance `json:"replicas,omitempty" yaml:"replicas,omitempty"`
Cron string `json:"cron,omitempty" yaml:"cron,omitempty"`
RunOnStart bool `json:"runOnStart,omitempty" yaml:"runOnStart,omitempty"`
Cron string `json:"cron,omitempty" yaml:"cron,omitempty" mapstructure:"CRON"`
RunOnStart bool `json:"runOnStart,omitempty" yaml:"runOnStart,omitempty" mapstructure:"RUN_ON_START"`
PrintConfigOnly bool `json:"printConfigOnly,omitempty" yaml:"printConfigOnly,omitempty" mapstructure:"PRINT_CONFIG_ONLY"`
ContinueOnError bool `json:"continueOnError,omitempty" yaml:"continueOnError,omitempty" mapstructure:"CONTINUE_ON_ERROR"`
API API `json:"api,omitempty" yaml:"api,omitempty"`
Features Features `json:"features,omitempty" yaml:"features,omitempty"`
LogLevel string `json:"logLevel,omitempty" yaml:"logLevel,omitempty" mapstructure:"LOG_LEVEL"`
API API `json:"api,omitempty" yaml:"api,omitempty" mapstructure:"API"`
Features Features `json:"features,omitempty" yaml:"features,omitempty" mapstructure:"FEATURES"`
}
// API configuration
type API struct {
Port int `json:"port,omitempty" yaml:"port,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
Password string `json:"password,omitempty" yaml:"password,omitempty"`
DarkMode bool `json:"darkMode,omitempty" yaml:"darkMode,omitempty"`
Port int `json:"port,omitempty" yaml:"port,omitempty" mapstructure:"PORT"`
Username string `json:"username,omitempty" yaml:"username,omitempty" mapstructure:"USERNAME"`
Password string `json:"password,omitempty" yaml:"password,omitempty" mapstructure:"PASSWORD"`
DarkMode bool `json:"darkMode,omitempty" yaml:"darkMode,omitempty" mapstructure:"DARK_MODE"`
}
// UniqueReplicas get unique replication instances
@@ -90,16 +89,16 @@ func (cfg *Config) Init() error {
// AdGuardInstance AdguardHome config instance
// +k8s:deepcopy-gen=true
type AdGuardInstance struct {
URL string `json:"url" yaml:"url"`
WebURL string `json:"webURL" yaml:"webURL"`
APIPath string `json:"apiPath,omitempty" yaml:"apiPath,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
Password string `json:"password,omitempty" yaml:"password,omitempty"`
Cookie string `json:"cookie,omitempty" yaml:"cookie,omitempty"`
InsecureSkipVerify bool `json:"insecureSkipVerify" yaml:"insecureSkipVerify"`
AutoSetup bool `json:"autoSetup" yaml:"autoSetup"`
InterfaceName string `json:"interfaceName,omitempty" yaml:"interfaceName,omitempty"`
DHCPServerEnabled *bool `json:"dhcpServerEnabled,omitempty" yaml:"dhcpServerEnabled,omitempty"`
URL string `json:"url" yaml:"url" mapstructure:"URL"`
WebURL string `json:"webURL" yaml:"webURL" mapstructure:"WEB_URL"`
APIPath string `json:"apiPath,omitempty" yaml:"apiPath,omitempty" mapstructure:"API_PATH"`
Username string `json:"username,omitempty" yaml:"username,omitempty" mapstructure:"USERNAME"`
Password string `json:"password,omitempty" yaml:"password,omitempty" mapstructure:"PASSWORD"`
Cookie string `json:"cookie,omitempty" yaml:"cookie,omitempty" mapstructure:"COOKIE"`
InsecureSkipVerify bool `json:"insecureSkipVerify" yaml:"insecureSkipVerify" mapstructure:"INSECURE_SKIP_VERIFY"`
AutoSetup bool `json:"autoSetup" yaml:"autoSetup" mapstructure:"AUTO_SETUP"`
InterfaceName string `json:"interfaceName,omitempty" yaml:"interfaceName,omitempty" mapstructure:"INTERFACE_NAME"`
DHCPServerEnabled *bool `json:"dhcpServerEnabled,omitempty" yaml:"dhcpServerEnabled,omitempty" mapstructure:"DHCP_SERVER_ENABLED"`
Host string `json:"-" yaml:"-"`
WebHost string `json:"-" yaml:"-"`