mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
cmd/cli: add config to control DNS watchdog
This commit is contained in:
committed by
Cuong Manh Le
parent
18a19a3aa2
commit
ec684348ed
@@ -40,7 +40,7 @@ const (
|
|||||||
upstreamPrefix = "upstream."
|
upstreamPrefix = "upstream."
|
||||||
upstreamOS = upstreamPrefix + "os"
|
upstreamOS = upstreamPrefix + "os"
|
||||||
upstreamPrivate = upstreamPrefix + "private"
|
upstreamPrivate = upstreamPrefix + "private"
|
||||||
dnsWatchdogInterval = time.Minute
|
dnsWatchdogDefaultInterval = 20 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
// ControlSocketName returns name for control unix socket.
|
// ControlSocketName returns name for control unix socket.
|
||||||
@@ -532,7 +532,27 @@ func (p *prog) setDNS() {
|
|||||||
return setDnsIgnoreUnusableInterface(i, nameservers)
|
return setDnsIgnoreUnusableInterface(i, nameservers)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
go p.dnsWatchdog(netIface, nameservers, allIfaces)
|
if p.dnsWatchdogEnabled() {
|
||||||
|
go p.dnsWatchdog(netIface, nameservers, allIfaces)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnsWatchdogEnabled reports whether DNS watchdog is enabled.
|
||||||
|
func (p *prog) dnsWatchdogEnabled() bool {
|
||||||
|
if ptr := p.cfg.Service.DnsWatchdogEnabled; ptr != nil {
|
||||||
|
return *ptr
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnsWatchdogDuration returns the time duration between each DNS watchdog loop.
|
||||||
|
func (p *prog) dnsWatchdogDuration() time.Duration {
|
||||||
|
if ptr := p.cfg.Service.DnsWatchdogInvterval; ptr != nil {
|
||||||
|
if (*ptr).Seconds() > 0 {
|
||||||
|
return *ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dnsWatchdogDefaultInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// dnsWatchdog watches for DNS changes on Darwin and Windows then re-applying ctrld's settings.
|
// dnsWatchdog watches for DNS changes on Darwin and Windows then re-applying ctrld's settings.
|
||||||
@@ -546,7 +566,7 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string, allIfaces
|
|||||||
mainLog.Load().Debug().Msg("start DNS settings watchdog")
|
mainLog.Load().Debug().Msg("start DNS settings watchdog")
|
||||||
ns := nameservers
|
ns := nameservers
|
||||||
slices.Sort(ns)
|
slices.Sort(ns)
|
||||||
ticker := time.NewTicker(dnsWatchdogInterval)
|
ticker := time.NewTicker(p.dnsWatchdogDuration())
|
||||||
logger := mainLog.Load().With().Str("iface", iface.Name).Logger()
|
logger := mainLog.Load().With().Str("iface", iface.Name).Logger()
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
if dnsChanged(iface, ns) {
|
if dnsChanged(iface, ns) {
|
||||||
|
|||||||
57
cmd/cli/prog_test.go
Normal file
57
cmd/cli/prog_test.go
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/Control-D-Inc/ctrld"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_prog_dnsWatchdogEnabled(t *testing.T) {
|
||||||
|
p := &prog{cfg: &ctrld.Config{}}
|
||||||
|
|
||||||
|
// Default value is true.
|
||||||
|
assert.True(t, p.dnsWatchdogEnabled())
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
enabled bool
|
||||||
|
}{
|
||||||
|
{"enabled", true},
|
||||||
|
{"disabled", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
p.cfg.Service.DnsWatchdogEnabled = &tc.enabled
|
||||||
|
assert.Equal(t, tc.enabled, p.dnsWatchdogEnabled())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_prog_dnsWatchdogInterval(t *testing.T) {
|
||||||
|
p := &prog{cfg: &ctrld.Config{}}
|
||||||
|
|
||||||
|
// Default value is 20s.
|
||||||
|
assert.Equal(t, dnsWatchdogDefaultInterval, p.dnsWatchdogDuration())
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
duration time.Duration
|
||||||
|
expected time.Duration
|
||||||
|
}{
|
||||||
|
{"valid", time.Minute, time.Minute},
|
||||||
|
{"zero", 0, dnsWatchdogDefaultInterval},
|
||||||
|
{"nagative", time.Duration(-1 * time.Minute), dnsWatchdogDefaultInterval},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
tc := tc
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
p.cfg.Service.DnsWatchdogInvterval = &tc.duration
|
||||||
|
assert.Equal(t, tc.expected, p.dnsWatchdogDuration())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
44
config.go
44
config.go
@@ -188,27 +188,29 @@ func (c *Config) FirstUpstream() *UpstreamConfig {
|
|||||||
|
|
||||||
// ServiceConfig specifies the general ctrld config.
|
// ServiceConfig specifies the general ctrld config.
|
||||||
type ServiceConfig struct {
|
type ServiceConfig struct {
|
||||||
LogLevel string `mapstructure:"log_level" toml:"log_level,omitempty"`
|
LogLevel string `mapstructure:"log_level" toml:"log_level,omitempty"`
|
||||||
LogPath string `mapstructure:"log_path" toml:"log_path,omitempty"`
|
LogPath string `mapstructure:"log_path" toml:"log_path,omitempty"`
|
||||||
CacheEnable bool `mapstructure:"cache_enable" toml:"cache_enable,omitempty"`
|
CacheEnable bool `mapstructure:"cache_enable" toml:"cache_enable,omitempty"`
|
||||||
CacheSize int `mapstructure:"cache_size" toml:"cache_size,omitempty"`
|
CacheSize int `mapstructure:"cache_size" toml:"cache_size,omitempty"`
|
||||||
CacheTTLOverride int `mapstructure:"cache_ttl_override" toml:"cache_ttl_override,omitempty"`
|
CacheTTLOverride int `mapstructure:"cache_ttl_override" toml:"cache_ttl_override,omitempty"`
|
||||||
CacheServeStale bool `mapstructure:"cache_serve_stale" toml:"cache_serve_stale,omitempty"`
|
CacheServeStale bool `mapstructure:"cache_serve_stale" toml:"cache_serve_stale,omitempty"`
|
||||||
CacheFlushDomains []string `mapstructure:"cache_flush_domains" toml:"cache_flush_domains" validate:"max=256"`
|
CacheFlushDomains []string `mapstructure:"cache_flush_domains" toml:"cache_flush_domains" validate:"max=256"`
|
||||||
MaxConcurrentRequests *int `mapstructure:"max_concurrent_requests" toml:"max_concurrent_requests,omitempty" validate:"omitempty,gte=0"`
|
MaxConcurrentRequests *int `mapstructure:"max_concurrent_requests" toml:"max_concurrent_requests,omitempty" validate:"omitempty,gte=0"`
|
||||||
DHCPLeaseFile string `mapstructure:"dhcp_lease_file_path" toml:"dhcp_lease_file_path" validate:"omitempty,file"`
|
DHCPLeaseFile string `mapstructure:"dhcp_lease_file_path" toml:"dhcp_lease_file_path" validate:"omitempty,file"`
|
||||||
DHCPLeaseFileFormat string `mapstructure:"dhcp_lease_file_format" toml:"dhcp_lease_file_format" validate:"required_unless=DHCPLeaseFile '',omitempty,oneof=dnsmasq isc-dhcp"`
|
DHCPLeaseFileFormat string `mapstructure:"dhcp_lease_file_format" toml:"dhcp_lease_file_format" validate:"required_unless=DHCPLeaseFile '',omitempty,oneof=dnsmasq isc-dhcp"`
|
||||||
DiscoverMDNS *bool `mapstructure:"discover_mdns" toml:"discover_mdns,omitempty"`
|
DiscoverMDNS *bool `mapstructure:"discover_mdns" toml:"discover_mdns,omitempty"`
|
||||||
DiscoverARP *bool `mapstructure:"discover_arp" toml:"discover_arp,omitempty"`
|
DiscoverARP *bool `mapstructure:"discover_arp" toml:"discover_arp,omitempty"`
|
||||||
DiscoverDHCP *bool `mapstructure:"discover_dhcp" toml:"discover_dhcp,omitempty"`
|
DiscoverDHCP *bool `mapstructure:"discover_dhcp" toml:"discover_dhcp,omitempty"`
|
||||||
DiscoverPtr *bool `mapstructure:"discover_ptr" toml:"discover_ptr,omitempty"`
|
DiscoverPtr *bool `mapstructure:"discover_ptr" toml:"discover_ptr,omitempty"`
|
||||||
DiscoverHosts *bool `mapstructure:"discover_hosts" toml:"discover_hosts,omitempty"`
|
DiscoverHosts *bool `mapstructure:"discover_hosts" toml:"discover_hosts,omitempty"`
|
||||||
DiscoverRefreshInterval int `mapstructure:"discover_refresh_interval" toml:"discover_refresh_interval,omitempty"`
|
DiscoverRefreshInterval int `mapstructure:"discover_refresh_interval" toml:"discover_refresh_interval,omitempty"`
|
||||||
ClientIDPref string `mapstructure:"client_id_preference" toml:"client_id_preference,omitempty" validate:"omitempty,oneof=host mac"`
|
ClientIDPref string `mapstructure:"client_id_preference" toml:"client_id_preference,omitempty" validate:"omitempty,oneof=host mac"`
|
||||||
MetricsQueryStats bool `mapstructure:"metrics_query_stats" toml:"metrics_query_stats,omitempty"`
|
MetricsQueryStats bool `mapstructure:"metrics_query_stats" toml:"metrics_query_stats,omitempty"`
|
||||||
MetricsListener string `mapstructure:"metrics_listener" toml:"metrics_listener,omitempty"`
|
MetricsListener string `mapstructure:"metrics_listener" toml:"metrics_listener,omitempty"`
|
||||||
Daemon bool `mapstructure:"-" toml:"-"`
|
DnsWatchdogEnabled *bool `mapstructure:"dns_watchdog_enabled" toml:"dns_watchdog_enabled,omitempty"`
|
||||||
AllocateIP bool `mapstructure:"-" toml:"-"`
|
DnsWatchdogInvterval *time.Duration `mapstructure:"dns_watchdog_interval" toml:"dns_watchdog_interval,omitempty"`
|
||||||
|
Daemon bool `mapstructure:"-" toml:"-"`
|
||||||
|
AllocateIP bool `mapstructure:"-" toml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NetworkConfig specifies configuration for networks where ctrld will handle requests.
|
// NetworkConfig specifies configuration for networks where ctrld will handle requests.
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@@ -22,6 +23,8 @@ func TestLoadConfig(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, "info", cfg.Service.LogLevel)
|
assert.Equal(t, "info", cfg.Service.LogLevel)
|
||||||
assert.Equal(t, "/path/to/log.log", cfg.Service.LogPath)
|
assert.Equal(t, "/path/to/log.log", cfg.Service.LogPath)
|
||||||
|
assert.Equal(t, false, *cfg.Service.DnsWatchdogEnabled)
|
||||||
|
assert.Equal(t, time.Duration(20*time.Second), *cfg.Service.DnsWatchdogInvterval)
|
||||||
|
|
||||||
assert.Len(t, cfg.Network, 2)
|
assert.Len(t, cfg.Network, 2)
|
||||||
assert.Contains(t, cfg.Network, "0")
|
assert.Contains(t, cfg.Network, "0")
|
||||||
|
|||||||
@@ -252,6 +252,27 @@ Specifying the `ip` and `port` of the Prometheus metrics server. The Prometheus
|
|||||||
- Required: no
|
- Required: no
|
||||||
- Default: ""
|
- Default: ""
|
||||||
|
|
||||||
|
### dns_watchdog_enabled
|
||||||
|
Checking DNS changes to network interfaces and reverting to ctrld's own settings.
|
||||||
|
|
||||||
|
The DNS watchdog process only runs on Windows and MacOS.
|
||||||
|
|
||||||
|
- Type: boolean
|
||||||
|
- Required: no
|
||||||
|
- Default: true
|
||||||
|
|
||||||
|
### dns_watchdog_interval
|
||||||
|
Time duration between each DNS watchdog iteration.
|
||||||
|
|
||||||
|
A duration string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix,
|
||||||
|
such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
|
||||||
|
|
||||||
|
If the time duration is non-positive, default value will be used.
|
||||||
|
|
||||||
|
- Type: time duration string
|
||||||
|
- Required: no
|
||||||
|
- Default: 20s
|
||||||
|
|
||||||
## Upstream
|
## Upstream
|
||||||
The `[upstream]` section specifies the DNS upstream servers that `ctrld` will forward DNS requests to.
|
The `[upstream]` section specifies the DNS upstream servers that `ctrld` will forward DNS requests to.
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ var sampleConfigContent = `
|
|||||||
[service]
|
[service]
|
||||||
log_level = "info"
|
log_level = "info"
|
||||||
log_path = "/path/to/log.log"
|
log_path = "/path/to/log.log"
|
||||||
|
dns_watchdog_enabled = false
|
||||||
|
dns_watchdog_interval = "20s"
|
||||||
|
|
||||||
[network.0]
|
[network.0]
|
||||||
name = "Home Wifi"
|
name = "Home Wifi"
|
||||||
|
|||||||
Reference in New Issue
Block a user