This is an automated email from the ASF dual-hosted git repository. zrhoffman pushed a commit to branch 6.0.x in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
commit 959f1ed338d2a812ffa0d662bdd42bde5e9a9aaa Author: John J. Rushford <[email protected]> AuthorDate: Tue Aug 31 14:46:49 2021 -0600 Updates to the tm-health-client (#6147) - fix to ensure marking parents up or down is only done using the configured reason code. - fixes an issue where available parents reported by TM are not marked up when 'enable-active-markdowns' disabled. - checks for updates to the config file applying new updates. - reloads the available traffic monitors list with a config file update. - reloads the available traffic monitors list if there are any errors encountered when polling a traffic monitor. - added a configuration parameter 'tm-update-cycles' to set a periodic refresh on the available traffic monitors list. - added a util module and renamed tmutil to tmagent - refactored unit tests. (cherry picked from commit 89fdc0e30c1adb4e8b86b4d98fd744d5b5b569f5) --- cache-config/tm-health-client/README.md | 21 +++- cache-config/tm-health-client/config/config.go | 87 ++++++++++---- .../tm-health-client/config/config_test.go | 14 ++- .../tm-health-client/tm-health-client-logrotate | 2 +- cache-config/tm-health-client/tm-health-client.go | 4 +- .../tm-health-client/tm-health-client.json | 3 +- .../{tmutil => tmagent}/test_files/bin/traffic_ctl | 0 .../test_files/etc/parent.config | 0 .../test_files/etc/strategies.yaml | 0 .../test_files/tm-health-client.json | 0 .../{tmutil/tmutil.go => tmagent/tmagent.go} | 126 ++++++++++++--------- .../tmutil_test.go => tmagent/tmagent_test.go} | 57 +++++++--- .../{tm-health-client.go => util/util.go} | 36 +++--- 13 files changed, 233 insertions(+), 117 deletions(-) diff --git a/cache-config/tm-health-client/README.md b/cache-config/tm-health-client/README.md index 6acb20e..d3a2ea8 100644 --- a/cache-config/tm-health-client/README.md +++ b/cache-config/tm-health-client/README.md @@ -58,6 +58,17 @@ otherwise unavailable, the tm-health-client will utilize the **Traffic Server** and **Traffic Monitor** has determined that the marked down host is now available, the client will then utilize the **Traffic Server** tool to mark the host back up. +Also on each polling cycle the configuration file, **tm-health-client.json** is +checked and a new config is reloaded if the file has changed since the last +polling cycle. The **Traffic Monitors** list is refreshed from **Traffic Ops**. + +If errors are encountered while polling a Traffic Monitor, the error is logged +and the **Traffic Monitors** list is refreshed from **Traffic Ops**. + +# REQUIREMENTS + +Requires Apache TrafficServer 8.1.0 or later. + # OPTIONS -f, -\-config-file=config-file @@ -97,6 +108,7 @@ Sample configuarion file: "to-url": "https://tp.cdn.com:443", "to-request-timeout-seconds": "5s", "tm-poll-interval-seconds": "60s", + "tm-update-cycles": 5, "trafficserver-config-dir": "/opt/trafficserver/etc/trafficserver", "trafficserver-bin-dir": "/opt/trafficserver/bin", } @@ -110,7 +122,8 @@ Sample configuarion file: When enabled, the client will actively mark down Traffic Server parents. When disabled, the client will only log that it would have marked down - Traffic Server parents + Traffic Server parents. Down Parents are always marked UP if Traffic Monitor + reports them available irregardless of this setting. ### reason-code @@ -140,6 +153,12 @@ Sample configuarion file: The polling interval in seconds used to update **Traffic Server** parent status. +### tm-update-cycles + + Each time a polling cycle completes a count is incremented. When the count + reaches **tm-update-cycles**, TrafficOps is polled for a new list of available + TrafficMonitors for the CDN and the poll count is reset to 0. + ### trafficserver-config-dir The location on the host where **Traffic Server** configuration files are diff --git a/cache-config/tm-health-client/config/config.go b/cache-config/tm-health-client/config/config.go index 5c5d8a8..f46d618 100644 --- a/cache-config/tm-health-client/config/config.go +++ b/cache-config/tm-health-client/config/config.go @@ -30,6 +30,7 @@ import ( "strings" "time" + "github.com/apache/trafficcontrol/cache-config/tm-health-client/util" "github.com/apache/trafficcontrol/lib/go-log" toclient "github.com/apache/trafficcontrol/traffic_ops/v3-client" @@ -45,6 +46,7 @@ const ( DefaultLogFile = "tm-health-client.log" DefaultTrafficServerConfigDir = "/opt/trafficserver/etc/trafficserver" DefaultTrafficServerBinDir = "/opt/trafficserver/bin" + DefaultTmUpdateCycles = 10 ) type Cfg struct { @@ -57,9 +59,11 @@ type Cfg struct { TOUrl string TOUser string TmPollIntervalSeconds string `json:"tm-poll-interval-seconds"` + TmUpdateCycles int `json:"tm-update-cycles"` TrafficServerConfigDir string `json:"trafficserver-config-dir"` TrafficServerBinDir string `json:"trafficserver-bin-dir"` TrafficMonitors map[string]bool `json:"trafficmonitors,omitempty"` + HealthClientConfigFile util.ConfigFile } type LogCfg struct { @@ -75,7 +79,7 @@ func (lcfg LogCfg) InfoLog() log.LogLocation { return log.LogLocation(lcfg.Lo func (lcfg LogCfg) DebugLog() log.LogLocation { return log.LogLocation(lcfg.LogLocationDebug) } func (lcfg LogCfg) EventLog() log.LogLocation { return log.LogLocation(log.LogLocationNull) } // not used -func readCredentials(cfg *Cfg) error { +func ReadCredentials(cfg *Cfg) error { fn := cfg.TOCredentialFile f, err := os.Open(fn) @@ -179,19 +183,24 @@ func GetConfig() (Cfg, error, bool) { return Cfg{}, errors.New("Initializing loggers: " + err.Error() + "\n"), false } + cf := util.ConfigFile{ + Filename: configFile, + LastModifyTime: 0, + } + cfg := Cfg{ - TrafficMonitors: make(map[string]bool, 0), + HealthClientConfigFile: cf, } - if err = LoadConfig(&cfg, configFile); err != nil { + if _, err = LoadConfig(&cfg); err != nil { return Cfg{}, errors.New(err.Error() + "\n"), false } - if err = readCredentials(&cfg); err != nil { + if err = ReadCredentials(&cfg); err != nil { return cfg, err, false } - err = GetTrafficMonitorsStatus(&cfg) + err = GetTrafficMonitors(&cfg) if err != nil { return cfg, err, false } @@ -199,7 +208,7 @@ func GetConfig() (Cfg, error, bool) { return cfg, nil, false } -func GetTrafficMonitorsStatus(cfg *Cfg) error { +func GetTrafficMonitors(cfg *Cfg) error { u, err := url.Parse(cfg.TOUrl) if err != nil { return errors.New("error parsing TOURL parameters: " + err.Error()) @@ -215,6 +224,7 @@ func GetTrafficMonitorsStatus(cfg *Cfg) error { return errors.New("error fetching Trafficmonitor server list: " + err.Error()) } + cfg.TrafficMonitors = make(map[string]bool, 0) for _, v := range srvs { if v.CDNName == cfg.CDNName && v.Status == "ONLINE" { hostname := v.HostName + "." + v.DomainName @@ -233,26 +243,65 @@ func GetRequestTimeout() time.Duration { return toRequestTimeout } -func LoadConfig(cfg *Cfg, configFile string) error { - content, err := ioutil.ReadFile(configFile) +func LoadConfig(cfg *Cfg) (bool, error) { + updated := false + configFile := cfg.HealthClientConfigFile.Filename + modTime, err := util.GetFileModificationTime(configFile) if err != nil { - return errors.New(err.Error()) + return updated, errors.New(err.Error()) } - if err = json.Unmarshal(content, cfg); err == nil { - tmPollingInterval, err = time.ParseDuration(cfg.TmPollIntervalSeconds) - if err != nil { - return errors.New("parsing TMPollingIntervalSeconds: " + err.Error()) - } - toRequestTimeout, err = time.ParseDuration(cfg.TORequestTimeOutSeconds) + + if modTime > cfg.HealthClientConfigFile.LastModifyTime { + log.Infoln("Loading a new config file.") + content, err := ioutil.ReadFile(configFile) if err != nil { - return errors.New("parsing TORequestTimeOutSeconds: " + err.Error()) + return updated, errors.New(err.Error()) } - if cfg.ReasonCode != "active" && cfg.ReasonCode != "local" { - return errors.New("invalid reason-code: " + cfg.ReasonCode + ", valid reason codes are 'active' or 'local'") + if err = json.Unmarshal(content, cfg); err == nil { + tmPollingInterval, err = time.ParseDuration(cfg.TmPollIntervalSeconds) + if err != nil { + return updated, errors.New("parsing TMPollingIntervalSeconds: " + err.Error()) + } + toRequestTimeout, err = time.ParseDuration(cfg.TORequestTimeOutSeconds) + if err != nil { + return updated, errors.New("parsing TORequestTimeOutSeconds: " + err.Error()) + } + if cfg.ReasonCode != "active" && cfg.ReasonCode != "local" { + return updated, errors.New("invalid reason-code: " + cfg.ReasonCode + ", valid reason codes are 'active' or 'local'") + } + if cfg.TrafficServerConfigDir == "" { + cfg.TrafficServerConfigDir = DefaultTrafficServerConfigDir + } + if cfg.TrafficServerBinDir == "" { + cfg.TrafficServerBinDir = DefaultTrafficServerBinDir + } + if cfg.TmUpdateCycles == 0 { + cfg.TmUpdateCycles = DefaultTmUpdateCycles + } } + + cfg.HealthClientConfigFile.LastModifyTime = modTime + updated = true } + return updated, nil +} - return err +func UpdateConfig(cfg *Cfg, newCfg *Cfg) { + log.Infoln("Installing config updates") + cfg.CDNName = newCfg.CDNName + cfg.EnableActiveMarkdowns = newCfg.EnableActiveMarkdowns + cfg.ReasonCode = newCfg.ReasonCode + cfg.TOCredentialFile = newCfg.TOCredentialFile + cfg.TORequestTimeOutSeconds = newCfg.TORequestTimeOutSeconds + cfg.TOPass = newCfg.TOPass + cfg.TOUrl = newCfg.TOUrl + cfg.TOUser = newCfg.TOUser + cfg.TmPollIntervalSeconds = newCfg.TmPollIntervalSeconds + cfg.TmUpdateCycles = newCfg.TmUpdateCycles + cfg.TrafficServerConfigDir = newCfg.TrafficServerConfigDir + cfg.TrafficServerBinDir = newCfg.TrafficServerBinDir + cfg.TrafficMonitors = newCfg.TrafficMonitors + cfg.HealthClientConfigFile = newCfg.HealthClientConfigFile } func Usage() { diff --git a/cache-config/tm-health-client/config/config_test.go b/cache-config/tm-health-client/config/config_test.go index 385439d..2bafe09 100644 --- a/cache-config/tm-health-client/config/config_test.go +++ b/cache-config/tm-health-client/config/config_test.go @@ -21,6 +21,8 @@ package config import ( "testing" + + "github.com/apache/trafficcontrol/cache-config/tm-health-client/util" ) const ( @@ -28,11 +30,17 @@ const ( ) func TestLoadConfig(t *testing.T) { + cf := util.ConfigFile{ + Filename: test_config_file, + LastModifyTime: 0, + } + cfg := Cfg{ - TrafficMonitors: make(map[string]bool, 0), + TrafficMonitors: make(map[string]bool, 0), + HealthClientConfigFile: cf, } - err := LoadConfig(&cfg, test_config_file) + _, err := LoadConfig(&cfg) if err != nil { t.Fatalf("failed to load %s: %s\n", test_config_file, err.Error()) } @@ -61,7 +69,7 @@ func TestLoadConfig(t *testing.T) { t.Fatalf("expected '%s', got %s\n", expect, creds) } - readCredentials(&cfg) + ReadCredentials(&cfg) expect = "https://tp.cdn.com:443" tourl := cfg.TOUrl diff --git a/cache-config/tm-health-client/tm-health-client-logrotate b/cache-config/tm-health-client/tm-health-client-logrotate index a3bfd30..9e97f3b 100644 --- a/cache-config/tm-health-client/tm-health-client-logrotate +++ b/cache-config/tm-health-client/tm-health-client-logrotate @@ -24,5 +24,5 @@ nomail notifempty rotate 10 - size 100M + size 5M } diff --git a/cache-config/tm-health-client/tm-health-client.go b/cache-config/tm-health-client/tm-health-client.go index b84bc61..b886e26 100644 --- a/cache-config/tm-health-client/tm-health-client.go +++ b/cache-config/tm-health-client/tm-health-client.go @@ -23,7 +23,7 @@ import ( "os" "github.com/apache/trafficcontrol/cache-config/tm-health-client/config" - "github.com/apache/trafficcontrol/cache-config/tm-health-client/tmutil" + "github.com/apache/trafficcontrol/cache-config/tm-health-client/tmagent" "github.com/apache/trafficcontrol/lib/go-log" ) @@ -44,7 +44,7 @@ func main() { os.Exit(Success) } - tmInfo, err := tmutil.NewParentInfo(cfg) + tmInfo, err := tmagent.NewParentInfo(cfg) if err != nil { log.Errorf("startup could not initialize ATS parent info: %s\n", err.Error()) } diff --git a/cache-config/tm-health-client/tm-health-client.json b/cache-config/tm-health-client/tm-health-client.json index 3523cda..8df62f6 100644 --- a/cache-config/tm-health-client/tm-health-client.json +++ b/cache-config/tm-health-client/tm-health-client.json @@ -6,6 +6,7 @@ "to-url": "https://tp.cdn.com:443", "to-request-timeout-seconds": "5s", "tm-poll-interval-seconds": "15s", + "tm-update-cycles": 5, "trafficserver-config-dir": "/opt/trafficserver/etc/trafficserver", - "trafficserver-bin-dir": "/opt/trafficserver/bin", + "trafficserver-bin-dir": "/opt/trafficserver/bin" } diff --git a/cache-config/tm-health-client/tmutil/test_files/bin/traffic_ctl b/cache-config/tm-health-client/tmagent/test_files/bin/traffic_ctl similarity index 100% rename from cache-config/tm-health-client/tmutil/test_files/bin/traffic_ctl rename to cache-config/tm-health-client/tmagent/test_files/bin/traffic_ctl diff --git a/cache-config/tm-health-client/tmutil/test_files/etc/parent.config b/cache-config/tm-health-client/tmagent/test_files/etc/parent.config similarity index 100% rename from cache-config/tm-health-client/tmutil/test_files/etc/parent.config rename to cache-config/tm-health-client/tmagent/test_files/etc/parent.config diff --git a/cache-config/tm-health-client/tmutil/test_files/etc/strategies.yaml b/cache-config/tm-health-client/tmagent/test_files/etc/strategies.yaml similarity index 100% rename from cache-config/tm-health-client/tmutil/test_files/etc/strategies.yaml rename to cache-config/tm-health-client/tmagent/test_files/etc/strategies.yaml diff --git a/cache-config/tm-health-client/tmutil/test_files/tm-health-client.json b/cache-config/tm-health-client/tmagent/test_files/tm-health-client.json similarity index 100% rename from cache-config/tm-health-client/tmutil/test_files/tm-health-client.json rename to cache-config/tm-health-client/tmagent/test_files/tm-health-client.json diff --git a/cache-config/tm-health-client/tmutil/tmutil.go b/cache-config/tm-health-client/tmagent/tmagent.go similarity index 86% rename from cache-config/tm-health-client/tmutil/tmutil.go rename to cache-config/tm-health-client/tmagent/tmagent.go index 45cb3d7..85329d8 100644 --- a/cache-config/tm-health-client/tmutil/tmutil.go +++ b/cache-config/tm-health-client/tmagent/tmagent.go @@ -1,4 +1,4 @@ -package tmutil +package tmagent /* * Licensed to the Apache Software Foundation (ASF) under one @@ -33,6 +33,7 @@ import ( "time" "github.com/apache/trafficcontrol/cache-config/tm-health-client/config" + "github.com/apache/trafficcontrol/cache-config/tm-health-client/util" "github.com/apache/trafficcontrol/lib/go-log" "github.com/apache/trafficcontrol/lib/go-tc" "github.com/apache/trafficcontrol/traffic_monitor/datareq" @@ -48,22 +49,15 @@ const ( ) type ParentAvailable interface { - available() bool -} - -// the necessary fields of a trafficserver parents config file needed to -// read the file and keep track of it's modification time. -type ParentConfigFile struct { - Filename string - LastModifyTime int64 + available(reasonCode string) bool } // the necessary data required to keep track of trafficserver config // files, lists of parents a trafficserver instance uses, and directory // locations used for configuration and trafficserver executables. type ParentInfo struct { - ParentDotConfig ParentConfigFile - StrategiesDotYaml ParentConfigFile + ParentDotConfig util.ConfigFile + StrategiesDotYaml util.ConfigFile TrafficServerBinDir string TrafficServerConfigDir string Parents map[string]ParentStatus @@ -93,15 +87,18 @@ type ParentStatus struct { // used to get the overall parent availablity from the // HostStatus markdown reasons. all markdown reasons // must be true for a parent to be considered available. -func (p ParentStatus) available() bool { - if !p.ActiveReason { - return false - } else if !p.LocalReason { - return false - } else if !p.ManualReason { - return false - } - return true +func (p ParentStatus) available(reasonCode string) bool { + rc := false + + switch reasonCode { + case "active": + rc = p.ActiveReason + case "local": + rc = p.LocalReason + case "manual": + rc = p.ManualReason + } + return rc } // used to log that a parent's status is either UP or @@ -184,22 +181,22 @@ type Strategies struct { func NewParentInfo(cfg config.Cfg) (*ParentInfo, error) { parentConfig := filepath.Join(cfg.TrafficServerConfigDir, ParentsFile) - modTime, err := getFileModificationTime(parentConfig) + modTime, err := util.GetFileModificationTime(parentConfig) if err != nil { return nil, errors.New("error reading " + ParentsFile + ": " + err.Error()) } - parents := ParentConfigFile{ + parents := util.ConfigFile{ Filename: parentConfig, LastModifyTime: modTime, } stratyaml := filepath.Join(cfg.TrafficServerConfigDir, StrategiesFile) - modTime, err = getFileModificationTime(stratyaml) + modTime, err = util.GetFileModificationTime(stratyaml) if err != nil { return nil, errors.New("error reading " + StrategiesFile + ": " + err.Error()) } - strategies := ParentConfigFile{ + strategies := util.ConfigFile{ Filename: filepath.Join(cfg.TrafficServerConfigDir, StrategiesFile), LastModifyTime: modTime, } @@ -259,10 +256,35 @@ func (c *ParentInfo) GetCacheStatuses() (map[tc.CacheName]datareq.CacheStatus, e // down in the trafficserver subsystem based upon that hosts current status and // the status that trafficmonitor health protocol has determined for a parent. func (c *ParentInfo) PollAndUpdateCacheStatus() { + cycleCount := 0 pollingInterval := config.GetTMPollingInterval() log.Infoln("polling started") for { + // check for config file updates + newCfg := config.Cfg{ + HealthClientConfigFile: c.Cfg.HealthClientConfigFile, + } + isNew, err := config.LoadConfig(&newCfg) + if err != nil { + log.Errorf("error reading changed config file %s: %s\n", c.Cfg.HealthClientConfigFile.Filename, err.Error()) + } + if isNew { + if err = config.ReadCredentials(&newCfg); err != nil { + log.Errorln("could not load credentials for config updates, keeping the old config") + } else { + if err = config.GetTrafficMonitors(&newCfg); err != nil { + log.Errorln("could not update the list of trafficmonitors, keeping the old config") + } else { + config.UpdateConfig(&c.Cfg, &newCfg) + log.Infof("the configuration has been successfully updated") + } + } + } + + // check for parent and strategies config file updates, and trafficserver + // host status changes. If an error is encountered reading data the current + // parents lists and hoststatus remains unchanged. if err := c.UpdateParentInfo(); err != nil { log.Errorf("could not load new ATS parent info: %s\n", err.Error()) } else { @@ -272,7 +294,14 @@ func (c *ParentInfo) PollAndUpdateCacheStatus() { // read traffic manager cache statuses. caches, err := c.GetCacheStatuses() if err != nil { - log.Errorln(err.Error()) + log.Errorf("error in TrafficMonitor polling: %s\n", err.Error()) + if err = config.GetTrafficMonitors(&c.Cfg); err != nil { + log.Errorln("could not update the list of trafficmonitors, keeping the old config") + } else { + log.Infoln("Updated TrafficMonitor statuses from TrafficOps") + } + time.Sleep(pollingInterval) + continue } for k, v := range caches { @@ -280,13 +309,10 @@ func (c *ParentInfo) PollAndUpdateCacheStatus() { cs, ok := c.Parents[hostName] if ok { tmAvailable := *v.CombinedAvailable - if cs.available() != tmAvailable { - if !c.Cfg.EnableActiveMarkdowns { - if !tmAvailable { - log.Infof("TM reports that %s is not available and should be marked DOWN but, mark downs are disabled by configuration", hostName) - } else { - log.Infof("TM reports that %s is available and should be marked UP but, mark up is disabled by configuration", hostName) - } + if cs.available(c.Cfg.ReasonCode) != tmAvailable { + // do not mark down if the configuration disables mark downs. + if !c.Cfg.EnableActiveMarkdowns && !tmAvailable { + log.Infof("TM reports that %s is not available and should be marked DOWN but, mark downs are disabled by configuration", hostName) } else { if err = c.markParent(cs.Fqdn, *v.Status, tmAvailable); err != nil { log.Errorln(err.Error()) @@ -296,6 +322,18 @@ func (c *ParentInfo) PollAndUpdateCacheStatus() { } } + // periodically update the TrafficMonitor list and statuses + if cycleCount == c.Cfg.TmUpdateCycles { + cycleCount = 0 + if err = config.GetTrafficMonitors(&c.Cfg); err != nil { + log.Errorln("could not update the list of trafficmonitors, keeping the old config") + } else { + log.Infoln("Updated TrafficMonitor statuses from TrafficOps") + } + } else { + cycleCount++ + } + time.Sleep(pollingInterval) } } @@ -305,11 +343,11 @@ func (c *ParentInfo) PollAndUpdateCacheStatus() { // availability is also updated to reflect the current state from // the trafficserver HostStatus subsystem. func (c *ParentInfo) UpdateParentInfo() error { - ptime, err := getFileModificationTime(c.ParentDotConfig.Filename) + ptime, err := util.GetFileModificationTime(c.ParentDotConfig.Filename) if err != nil { return errors.New("error reading " + ParentsFile + ": " + err.Error()) } - stime, err := getFileModificationTime(c.StrategiesDotYaml.Filename) + stime, err := util.GetFileModificationTime(c.StrategiesDotYaml.Filename) if err != nil { return errors.New("error reading " + StrategiesFile + ": " + err.Error()) } @@ -372,22 +410,6 @@ func (c *ParentInfo) findATrafficMonitor() (string, error) { return tmHostname, nil } -// get the file modification times for a trafficserver configuration -// file. -func getFileModificationTime(fn string) (int64, error) { - f, err := os.Open(fn) - if err != nil { - return 0, errors.New("opening " + fn + ": " + err.Error()) - } - defer f.Close() - - finfo, err := f.Stat() - if err != nil { - return 0, errors.New("unable to get file status for " + fn + ": " + err.Error()) - } - return finfo.ModTime().UnixNano(), nil -} - // parse out the hostname of a parent listed in parents.config // or 'strategies.yaml'. the hostname can be an IP address. func parseFqdn(fqdn string) string { @@ -507,8 +529,8 @@ func (c *ParentInfo) readHostStatus(parentStatus map[string]ParentStatus) error parentStatus[hostName] = pstat log.Infof("added Host '%s' from ATS Host Status to the parents map\n", hostName) } else { - available := pstat.available() - if pv.available() != available { + available := pstat.available(c.Cfg.ReasonCode) + if pv.available(c.Cfg.ReasonCode) != available { log.Infof("host status for '%s' has changed to %s\n", hostName, pstat.Status()) parentStatus[hostName] = pstat } diff --git a/cache-config/tm-health-client/tmutil/tmutil_test.go b/cache-config/tm-health-client/tmagent/tmagent_test.go similarity index 81% rename from cache-config/tm-health-client/tmutil/tmutil_test.go rename to cache-config/tm-health-client/tmagent/tmagent_test.go index 417612d..f3ea96c 100644 --- a/cache-config/tm-health-client/tmutil/tmutil_test.go +++ b/cache-config/tm-health-client/tmagent/tmagent_test.go @@ -1,4 +1,4 @@ -package tmutil +package tmagent /* * Licensed to the Apache Software Foundation (ASF) under one @@ -22,6 +22,7 @@ package tmutil import ( "fmt" "github.com/apache/trafficcontrol/cache-config/tm-health-client/config" + "github.com/apache/trafficcontrol/cache-config/tm-health-client/util" "testing" ) @@ -30,11 +31,17 @@ const ( ) func TestReadParentDotConfig(t *testing.T) { + cf := util.ConfigFile{ + Filename: test_config_file, + LastModifyTime: 0, + } + cfg := config.Cfg{ - TrafficMonitors: make(map[string]bool, 0), + TrafficMonitors: make(map[string]bool, 0), + HealthClientConfigFile: cf, } - parentDotConfig := ParentConfigFile{ + parentDotConfig := util.ConfigFile{ Filename: "test_files/etc/parent.config", LastModifyTime: 1, } @@ -44,7 +51,7 @@ func TestReadParentDotConfig(t *testing.T) { Cfg: cfg, } - err := config.LoadConfig(&cfg, test_config_file) + _, err := config.LoadConfig(&cfg) if err != nil { t.Fatalf("failed to load %s: %s\n", test_config_file, err.Error()) } @@ -61,11 +68,17 @@ func TestReadParentDotConfig(t *testing.T) { } func TestReadStrategiesDotYaml(t *testing.T) { + cf := util.ConfigFile{ + Filename: test_config_file, + LastModifyTime: 0, + } + cfg := config.Cfg{ - TrafficMonitors: make(map[string]bool, 0), + TrafficMonitors: make(map[string]bool, 0), + HealthClientConfigFile: cf, } - strategiesDotYaml := ParentConfigFile{ + strategiesDotYaml := util.ConfigFile{ Filename: "test_files/etc/strategies.yaml", LastModifyTime: 1, } @@ -75,7 +88,7 @@ func TestReadStrategiesDotYaml(t *testing.T) { Cfg: cfg, } - err := config.LoadConfig(&cfg, test_config_file) + _, err := config.LoadConfig(&cfg) if err != nil { t.Fatalf("failed to load %s: %s\n", test_config_file, err.Error()) } @@ -92,8 +105,14 @@ func TestReadStrategiesDotYaml(t *testing.T) { } func TestReadHostStatus(t *testing.T) { + cf := util.ConfigFile{ + Filename: test_config_file, + LastModifyTime: 0, + } + cfg := config.Cfg{ - TrafficMonitors: make(map[string]bool, 0), + TrafficMonitors: make(map[string]bool, 0), + HealthClientConfigFile: cf, } pi := ParentInfo{ @@ -101,7 +120,7 @@ func TestReadHostStatus(t *testing.T) { Cfg: cfg, } - err := config.LoadConfig(&cfg, test_config_file) + _, err := config.LoadConfig(&cfg) if err != nil { t.Fatalf("failed to load %s: %s\n", test_config_file, err.Error()) } @@ -119,15 +138,21 @@ func TestReadHostStatus(t *testing.T) { } func TestFindATrafficMonitor(t *testing.T) { + cf := util.ConfigFile{ + Filename: test_config_file, + LastModifyTime: 0, + } + cfg := config.Cfg{ - TrafficMonitors: make(map[string]bool, 0), + TrafficMonitors: make(map[string]bool, 0), + HealthClientConfigFile: cf, } pi := ParentInfo{ Cfg: cfg, } - err := config.LoadConfig(&cfg, test_config_file) + _, err := config.LoadConfig(&cfg) if err != nil { t.Fatalf("failed to load %s: %s\n", test_config_file, err.Error()) } @@ -154,7 +179,7 @@ func TestParentStatus(t *testing.T) { ManualReason: false, } - available := pstat.available() + available := pstat.available("manual") if available { t.Fatalf("expected parent status for %s to be false, got %v\n", pstat.Fqdn, available) @@ -164,7 +189,7 @@ func TestParentStatus(t *testing.T) { t.Fatalf("expected status 'DOWN' got %s\n", status) } pstat.ManualReason = true - available = pstat.available() + available = pstat.available("active") if !available { t.Fatalf("expected parent status for %s to be true, got %v\n", pstat.Fqdn, available) @@ -174,7 +199,7 @@ func TestParentStatus(t *testing.T) { t.Fatalf("expected status 'UP' got %s\n", status) } pstat.LocalReason = false - available = pstat.available() + available = pstat.available("local") if available { t.Fatalf("expected parent status for %s to be false, got %v\n", pstat.Fqdn, available) @@ -186,7 +211,7 @@ func TestParentStatus(t *testing.T) { pstat.LocalReason = true pstat.ActiveReason = false - available = pstat.available() + available = pstat.available("active") if available { t.Fatalf("expected parent status for %s to be false, got %v\n", pstat.Fqdn, available) @@ -196,7 +221,7 @@ func TestParentStatus(t *testing.T) { t.Fatalf("expected status 'DOWN' got %s\n", status) } pstat.ActiveReason = true - available = pstat.available() + available = pstat.available("active") if !available { t.Fatalf("expected parent status for %s to be false, got %v\n", pstat.Fqdn, available) diff --git a/cache-config/tm-health-client/tm-health-client.go b/cache-config/tm-health-client/util/util.go similarity index 57% copy from cache-config/tm-health-client/tm-health-client.go copy to cache-config/tm-health-client/util/util.go index b84bc61..951c701 100644 --- a/cache-config/tm-health-client/tm-health-client.go +++ b/cache-config/tm-health-client/util/util.go @@ -1,4 +1,4 @@ -package main +package util /* * Licensed to the Apache Software Foundation (ASF) under one @@ -20,34 +20,26 @@ package main */ import ( + "errors" "os" - - "github.com/apache/trafficcontrol/cache-config/tm-health-client/config" - "github.com/apache/trafficcontrol/cache-config/tm-health-client/tmutil" - "github.com/apache/trafficcontrol/lib/go-log" ) -const ( - Success = 0 - ConfigError = 166 -) +type ConfigFile struct { + Filename string + LastModifyTime int64 +} -func main() { - cfg, err, helpflag := config.GetConfig() +// get the file modification times for a configuration file. +func GetFileModificationTime(fn string) (int64, error) { + f, err := os.Open(fn) if err != nil { - log.Errorln(err.Error()) - os.Exit(ConfigError) - } else { - log.Infoln("startup complete, the config has been loaded") - } - if helpflag { // user used --help option - os.Exit(Success) + return 0, errors.New("opening " + fn + ": " + err.Error()) } + defer f.Close() - tmInfo, err := tmutil.NewParentInfo(cfg) + finfo, err := f.Stat() if err != nil { - log.Errorf("startup could not initialize ATS parent info: %s\n", err.Error()) + return 0, errors.New("unable to get file status for " + fn + ": " + err.Error()) } - - tmInfo.PollAndUpdateCacheStatus() + return finfo.ModTime().UnixNano(), nil }
