mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-07-04 01:07:49 +02:00
cmd/cli: do not watch for config change during self-check
Once the listener is ready, the config was generated correctly on disk, so we should just re-read the content instead of watching for changes.
This commit is contained in:
committed by
Cuong Manh Le
parent
1012bf063f
commit
3ddcb84db8
+33
-58
@@ -21,12 +21,10 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/Masterminds/semver"
|
"github.com/Masterminds/semver"
|
||||||
"github.com/cuonglm/osinfo"
|
"github.com/cuonglm/osinfo"
|
||||||
"github.com/fsnotify/fsnotify"
|
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
"github.com/kardianos/service"
|
"github.com/kardianos/service"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
@@ -251,13 +249,14 @@ func initCLI() {
|
|||||||
// A buffer channel to gather log output from runCmd and report
|
// A buffer channel to gather log output from runCmd and report
|
||||||
// to user in case self-check process failed.
|
// to user in case self-check process failed.
|
||||||
runCmdLogCh := make(chan string, 256)
|
runCmdLogCh := make(chan string, 256)
|
||||||
if dir, err := userHomeDir(); err == nil {
|
ud, err := userHomeDir()
|
||||||
setWorkingDirectory(sc, dir)
|
sockDir := ud
|
||||||
|
if err == nil {
|
||||||
|
setWorkingDirectory(sc, ud)
|
||||||
if configPath == "" && writeDefaultConfig {
|
if configPath == "" && writeDefaultConfig {
|
||||||
defaultConfigFile = filepath.Join(dir, defaultConfigFile)
|
defaultConfigFile = filepath.Join(ud, defaultConfigFile)
|
||||||
}
|
}
|
||||||
sc.Arguments = append(sc.Arguments, "--homedir="+dir)
|
sc.Arguments = append(sc.Arguments, "--homedir="+ud)
|
||||||
sockDir := dir
|
|
||||||
if d, err := socketDir(); err == nil {
|
if d, err := socketDir(); err == nil {
|
||||||
sockDir = d
|
sockDir = d
|
||||||
}
|
}
|
||||||
@@ -339,7 +338,7 @@ func initCLI() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ok, status, err := selfCheckStatus(s)
|
ok, status, err := selfCheckStatus(s, ud, sockDir)
|
||||||
switch {
|
switch {
|
||||||
case ok && status == service.StatusRunning:
|
case ok && status == service.StatusRunning:
|
||||||
mainLog.Load().Notice().Msg("Service started")
|
mainLog.Load().Notice().Msg("Service started")
|
||||||
@@ -1581,7 +1580,7 @@ func defaultIfaceName() string {
|
|||||||
// - External testing, ensuring query could be sent from ctrld -> upstream.
|
// - External testing, ensuring query could be sent from ctrld -> upstream.
|
||||||
//
|
//
|
||||||
// Self-check is considered success only if both tests are ok.
|
// Self-check is considered success only if both tests are ok.
|
||||||
func selfCheckStatus(s service.Service) (bool, service.Status, error) {
|
func selfCheckStatus(s service.Service, homedir, sockDir string) (bool, service.Status, error) {
|
||||||
status, err := s.Status()
|
status, err := s.Status()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Load().Warn().Err(err).Msg("could not get service status")
|
mainLog.Load().Warn().Err(err).Msg("could not get service status")
|
||||||
@@ -1596,73 +1595,50 @@ func selfCheckStatus(s service.Service) (bool, service.Status, error) {
|
|||||||
return true, status, nil
|
return true, status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
dir, err := socketDir()
|
|
||||||
if err != nil {
|
|
||||||
mainLog.Load().Error().Err(err).Msg("failed to get ctrld listener status: could not get home directory")
|
|
||||||
return false, status, err
|
|
||||||
}
|
|
||||||
mainLog.Load().Debug().Msg("waiting for ctrld listener to be ready")
|
mainLog.Load().Debug().Msg("waiting for ctrld listener to be ready")
|
||||||
cc := newSocketControlClient(s, dir)
|
cc := newSocketControlClient(s, sockDir)
|
||||||
if cc == nil {
|
if cc == nil {
|
||||||
return false, status, errors.New("could not connect to control server")
|
return false, status, errors.New("could not connect to control server")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not a ctrld upstream, return status as-is.
|
v = viper.NewWithOptions(viper.KeyDelimiter("::"))
|
||||||
if cfg.FirstUpstream().VerifyDomain() == "" {
|
ctrld.SetConfigNameWithPath(v, "ctrld", homedir)
|
||||||
|
if configPath != "" {
|
||||||
|
v.SetConfigFile(configPath)
|
||||||
|
}
|
||||||
|
if err := v.ReadInConfig(); err != nil {
|
||||||
|
mainLog.Load().Error().Err(err).Msgf("failed to re-read configuration file: %s", v.ConfigFileUsed())
|
||||||
|
return false, status, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg = ctrld.Config{}
|
||||||
|
if err := v.Unmarshal(&cfg); err != nil {
|
||||||
|
mainLog.Load().Error().Err(err).Msg("failed to update new config")
|
||||||
|
return false, status, err
|
||||||
|
}
|
||||||
|
|
||||||
|
selfCheckExternalDomain := cfg.FirstUpstream().VerifyDomain()
|
||||||
|
if selfCheckExternalDomain == "" {
|
||||||
|
// Nothing to do, return the status as-is.
|
||||||
return true, status, nil
|
return true, status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mainLog.Load().Debug().Msg("ctrld listener is ready")
|
mainLog.Load().Debug().Msg("ctrld listener is ready")
|
||||||
mainLog.Load().Debug().Msg("performing self-check")
|
mainLog.Load().Debug().Msg("performing self-check")
|
||||||
var (
|
|
||||||
lcChanged map[string]*ctrld.ListenerConfig
|
|
||||||
ucChanged map[string]*ctrld.UpstreamConfig
|
|
||||||
mu sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := v.ReadInConfig(); err != nil {
|
|
||||||
mainLog.Load().Fatal().Err(err).Msg("failed to read new config")
|
|
||||||
}
|
|
||||||
if err := v.Unmarshal(&cfg); err != nil {
|
|
||||||
mainLog.Load().Fatal().Err(err).Msg("failed to update new config")
|
|
||||||
}
|
|
||||||
domain := cfg.FirstUpstream().VerifyDomain()
|
|
||||||
if domain == "" {
|
|
||||||
// Nothing to do, return the status as-is.
|
|
||||||
return true, status, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
v.OnConfigChange(func(in fsnotify.Event) {
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
if err := v.UnmarshalKey("listener", &lcChanged); err != nil {
|
|
||||||
mainLog.Load().Error().Msgf("failed to unmarshal listener config: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg.Listener = lcChanged
|
|
||||||
if err := v.UnmarshalKey("upstream", &ucChanged); err != nil {
|
|
||||||
mainLog.Load().Error().Msgf("failed to unmarshal upstream config: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cfg.Upstream = ucChanged
|
|
||||||
})
|
|
||||||
v.WatchConfig()
|
|
||||||
|
|
||||||
lc := cfg.FirstListener()
|
lc := cfg.FirstListener()
|
||||||
addr := net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port))
|
addr := net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port))
|
||||||
getInternalDomainFn := func() string { return selfCheckInternalTestDomain }
|
if err := selfCheckResolveDomain(context.TODO(), addr, "internal", selfCheckInternalTestDomain); err != nil {
|
||||||
getExternalDomainFn := func() string { return cfg.FirstUpstream().VerifyDomain() }
|
|
||||||
if err := selfCheckResolveDomain(context.TODO(), addr, "internal", getInternalDomainFn); err != nil {
|
|
||||||
return false, status, err
|
return false, status, err
|
||||||
}
|
}
|
||||||
if err := selfCheckResolveDomain(context.TODO(), addr, "external", getExternalDomainFn); err != nil {
|
if err := selfCheckResolveDomain(context.TODO(), addr, "external", selfCheckExternalDomain); err != nil {
|
||||||
return false, status, err
|
return false, status, err
|
||||||
}
|
}
|
||||||
return true, status, nil
|
return true, status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// selfCheckResolveDomain performs DNS test query against ctrld listener.
|
// selfCheckResolveDomain performs DNS test query against ctrld listener.
|
||||||
func selfCheckResolveDomain(ctx context.Context, addr, scope string, getDomainFn func() string) error {
|
func selfCheckResolveDomain(ctx context.Context, addr, scope string, domain string) error {
|
||||||
bo := backoff.NewBackoff("self-check", logf, 10*time.Second)
|
bo := backoff.NewBackoff("self-check", logf, 10*time.Second)
|
||||||
bo.LogLongerThan = 500 * time.Millisecond
|
bo.LogLongerThan = 500 * time.Millisecond
|
||||||
maxAttempts := 20
|
maxAttempts := 20
|
||||||
@@ -1672,11 +1648,10 @@ func selfCheckResolveDomain(ctx context.Context, addr, scope string, getDomainFn
|
|||||||
lastAnswer *dns.Msg
|
lastAnswer *dns.Msg
|
||||||
lastErr error
|
lastErr error
|
||||||
)
|
)
|
||||||
domain := ""
|
|
||||||
for i := 0; i < maxAttempts; i++ {
|
for i := 0; i < maxAttempts; i++ {
|
||||||
domain = getDomainFn()
|
|
||||||
if domain == "" {
|
if domain == "" {
|
||||||
continue
|
return errors.New("empty test domain")
|
||||||
}
|
}
|
||||||
m := new(dns.Msg)
|
m := new(dns.Msg)
|
||||||
m.SetQuestion(domain+".", dns.TypeA)
|
m.SetQuestion(domain+".", dns.TypeA)
|
||||||
|
|||||||
Reference in New Issue
Block a user