Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ linters:
- ineffassign
- unused
- govet
#- errcheck
- errcheck
- staticcheck
exclusions:
generated: lax
Expand Down
13 changes: 10 additions & 3 deletions cmd/healthchecker/health_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,18 @@ func main() {
}
})
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.CommandLine.MarkHidden("vmodule")
pflag.CommandLine.MarkHidden("logtostderr")
if err := pflag.CommandLine.MarkHidden("vmodule"); err != nil {
klog.Fatalf("Failed to mark hidden flag 'vmodule': %v", err)
}
if err := pflag.CommandLine.MarkHidden("logtostderr"); err != nil {
klog.Fatalf("Failed to mark hidden flag 'logtostderr': %v", err)
}

hco := options.NewHealthCheckerOptions()
hco.AddFlags(pflag.CommandLine)
if err := hco.AddFlags(pflag.CommandLine); err != nil {
fmt.Println(err)
os.Exit(int(types.Unknown))
}
pflag.Parse()
hco.SetDefaults()
if err := hco.IsValid(); err != nil {
Expand Down
7 changes: 5 additions & 2 deletions cmd/healthchecker/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,14 @@ type HealthCheckerOptions struct {
}

// AddFlags adds health checker command line options to pflag.
func (hco *HealthCheckerOptions) AddFlags(fs *pflag.FlagSet) {
func (hco *HealthCheckerOptions) AddFlags(fs *pflag.FlagSet) error {
fs.StringVar(&hco.Component, "component", types.KubeletComponent,
"The component to check health for. Supports kubelet, docker, kube-proxy, and cri")
// Deprecated: For backward compatibility on linux environment. Going forward "service" will be used instead of systemd-service
if runtime.GOOS == "linux" {
fs.MarkDeprecated("systemd-service", "please use --service flag instead")
if err := fs.MarkDeprecated("systemd-service", "please use --service flag instead"); err != nil {
return fmt.Errorf("failed to mark deprecated flag 'systemd-service': %w", err)
}
fs.StringVar(&hco.Service, "systemd-service", "",
"The underlying service responsible for the component. Set to the corresponding component for docker and kubelet, containerd for cri.")
}
Expand All @@ -73,6 +75,7 @@ func (hco *HealthCheckerOptions) AddFlags(fs *pflag.FlagSet) {
"The time to wait before marking the component as unhealthy.")
fs.Var(&hco.LogPatterns, "log-pattern",
"The log pattern to look for in service journald logs. The format for flag value <failureThresholdCount>:<logPattern>")
return nil
}

// IsValid validates health checker command line options.
Expand Down
24 changes: 18 additions & 6 deletions cmd/nodeproblemdetector/node_problem_detector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ func writeTempFile(t *testing.T, ext string, contents string) (string, error) {
fileName := f.Name()

if err := os.WriteFile(fileName, []byte(contents), 0o644); err != nil {
os.Remove(fileName)
if err := os.Remove(fileName); err != nil {
t.Logf("Failed to remove temporary file %s: %v", fileName, err)
}
return "", fmt.Errorf("cannot write config to temp file %s, %v", fileName, err)
}

Expand All @@ -106,16 +108,22 @@ func writeTempFile(t *testing.T, ext string, contents string) (string, error) {
func setupNPD(t *testing.T) (*options.NodeProblemDetectorOptions, func()) {
fakeLogFileName, err := writeTempFile(t, "log", "")
if err != nil {
os.Remove(fakeLogFileName)
if err := os.Remove(fakeLogFileName); err != nil {
t.Logf("Failed to remove temporary file %s: %v", fakeLogFileName, err)
}
t.Fatalf("cannot create temp config file, %v", err)
}

fakeConfigFileContents := fmt.Sprintf(fakeConfigFilePattern, strings.ReplaceAll(fakeLogFileName, "\\", "\\\\"))

fakeConfigFileName, err := writeTempFile(t, "json", fakeConfigFileContents)
if err != nil {
os.Remove(fakeLogFileName)
os.Remove(fakeConfigFileName)
if err := os.Remove(fakeLogFileName); err != nil {
t.Logf("Failed to remove temporary file %s: %v", fakeLogFileName, err)
}
if err := os.Remove(fakeConfigFileName); err != nil {
t.Logf("Failed to remove temporary file %s: %v", fakeConfigFileName, err)
}
t.Fatalf("cannot create temp config file, %v", err)
}

Expand All @@ -126,7 +134,11 @@ func setupNPD(t *testing.T) (*options.NodeProblemDetectorOptions, func()) {
},
},
}, func() {
os.Remove(fakeLogFileName)
os.Remove(fakeConfigFileName)
if err := os.Remove(fakeLogFileName); err != nil {
t.Logf("Failed to remove temporary file %s: %v", fakeLogFileName, err)
}
if err := os.Remove(fakeConfigFileName); err != nil {
t.Logf("Failed to remove temporary file %s: %v", fakeConfigFileName, err)
}
}
}
12 changes: 9 additions & 3 deletions cmd/nodeproblemdetector/node_problem_detector_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,17 @@ func main() {
}
})
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.CommandLine.MarkHidden("vmodule")
pflag.CommandLine.MarkHidden("logtostderr")
if err := pflag.CommandLine.MarkHidden("vmodule"); err != nil {
klog.Fatalf("Failed to mark hidden flag 'vmodule': %v", err)
}
if err := pflag.CommandLine.MarkHidden("logtostderr"); err != nil {
klog.Fatalf("Failed to mark hidden flag 'logtostderr': %v", err)
}

npdo := options.NewNodeProblemDetectorOptions()
npdo.AddFlags(pflag.CommandLine)
if err := npdo.AddFlags(pflag.CommandLine); err != nil {
klog.Fatalf("Failed to add flags: %v", err)
}

pflag.Parse()
if err := npdMain(context.Background(), npdo); err != nil {
Expand Down
12 changes: 9 additions & 3 deletions cmd/nodeproblemdetector/node_problem_detector_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,17 @@ func main() {
}
})
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
pflag.CommandLine.MarkHidden("vmodule")
pflag.CommandLine.MarkHidden("logtostderr")
if err := pflag.CommandLine.MarkHidden("vmodule"); err != nil {
klog.Fatalf("Failed to mark hidden flag 'vmodule': %v", err)
}
if err := pflag.CommandLine.MarkHidden("logtostderr"); err != nil {
klog.Fatalf("Failed to mark hidden flag 'logtostderr': %v", err)
}

npdo := options.NewNodeProblemDetectorOptions()
npdo.AddFlags(pflag.CommandLine)
if err := npdo.AddFlags(pflag.CommandLine); err != nil {
klog.Fatalf("Failed to add flags: %v", err)
}

pflag.Parse()

Expand Down
11 changes: 8 additions & 3 deletions cmd/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,17 @@ func NewNodeProblemDetectorOptions() *NodeProblemDetectorOptions {
}

// AddFlags adds node problem detector command line options to pflag.
func (npdo *NodeProblemDetectorOptions) AddFlags(fs *pflag.FlagSet) {
func (npdo *NodeProblemDetectorOptions) AddFlags(fs *pflag.FlagSet) error {
fs.StringSliceVar(&npdo.SystemLogMonitorConfigPaths, "system-log-monitors",
[]string{}, "List of paths to system log monitor config files, comma separated.")
fs.MarkDeprecated("system-log-monitors", "replaced by --config.system-log-monitor. NPD will panic if both --system-log-monitors and --config.system-log-monitor are set.")
if err := fs.MarkDeprecated("system-log-monitors", "replaced by --config.system-log-monitor. NPD will panic if both --system-log-monitors and --config.system-log-monitor are set."); err != nil {
return fmt.Errorf("failed to mark 'system-log-monitors' as deprecated: %w", err)
}
fs.StringSliceVar(&npdo.CustomPluginMonitorConfigPaths, "custom-plugin-monitors",
[]string{}, "List of paths to custom plugin monitor config files, comma separated.")
fs.MarkDeprecated("custom-plugin-monitors", "replaced by --config.custom-plugin-monitor. NPD will panic if both --custom-plugin-monitors and --config.custom-plugin-monitor are set.")
if err := fs.MarkDeprecated("custom-plugin-monitors", "replaced by --config.custom-plugin-monitor. NPD will panic if both --custom-plugin-monitors and --config.custom-plugin-monitor are set."); err != nil {
return fmt.Errorf("failed to mark 'custom-plugin-monitors' as deprecated: %w", err)
}
fs.BoolVar(&npdo.EnableK8sExporter, "enable-k8s-exporter", true, "Enables reporting to Kubernetes API server.")
fs.StringVar(&npdo.EventNamespace, "event-namespace", "", "Namespace for recorded Kubernetes events.")
fs.StringVar(&npdo.ApiServerOverride, "apiserver-override",
Expand Down Expand Up @@ -149,6 +153,7 @@ func (npdo *NodeProblemDetectorOptions) AddFlags(fs *pflag.FlagSet) {
problemDaemonName,
problemdaemon.GetProblemDaemonHandlerOrDie(problemDaemonName).CmdOptionDescription))
}
return nil
}

// ValidOrDie validates node problem detector command line options.
Expand Down
4 changes: 3 additions & 1 deletion pkg/custompluginmonitor/plugin/plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ func TestNewPluginRun(t *testing.T) {
utMeta := v
t.Run(desp, func(t *testing.T) {
conf := cpmtypes.CustomPluginConfig{}
(&conf).ApplyConfiguration()
if err := (&conf).ApplyConfiguration(); err != nil {
t.Errorf("Failed to apply configuration: %v", err)
}
p := Plugin{config: conf}
gotExitStatus, gotOutput := p.run(utMeta.Rule)
// cut at position max_output_length if expected output is longer than max_output_length bytes
Expand Down
4 changes: 3 additions & 1 deletion pkg/custompluginmonitor/types/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,9 @@ func TestCustomPluginConfigApplyConfiguration(t *testing.T) {
}

for desp, utMeta := range utMetas {
(&utMeta.Orig).ApplyConfiguration()
if err := (&utMeta.Orig).ApplyConfiguration(); err != nil {
t.Errorf("Error in apply configuration for %q: %v", desp, err)
}
if !reflect.DeepEqual(utMeta.Orig, utMeta.Wanted) {
t.Errorf("Error in apply configuration for %q", desp)
t.Errorf("Wanted: %+v. \nGot: %+v", utMeta.Wanted, utMeta.Orig)
Expand Down
4 changes: 3 additions & 1 deletion pkg/exporters/k8sexporter/k8s_exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ func (ke *k8sExporter) startHTTPReporting(npdo *options.NodeProblemDetectorOptio
// logic in the future.
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Write([]byte("ok"))
if _, err := w.Write([]byte("ok")); err != nil {
klog.Errorf("Failed to write response: %v", err)
}
})

// Add the handler to serve condition http request.
Expand Down
12 changes: 9 additions & 3 deletions pkg/healthchecker/health_checker_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,19 @@ func getRepairFunc(hco *options.HealthCheckerOptions) func() {
// Use "docker ps" for docker health check. Not using crictl for docker to remove
// dependency on the kubelet.
return func() {
execCommand(types.CmdTimeout, "pkill", "-SIGUSR1", "dockerd")
execCommand(types.CmdTimeout, "systemctl", "kill", "--kill-who=main", hco.Service)
if _, err := execCommand(types.CmdTimeout, "pkill", "-SIGUSR1", "dockerd"); err != nil {
klog.Errorf("Failed to send SIGUSR1 to dockerd: %v", err)
}
if _, err := execCommand(types.CmdTimeout, "systemctl", "kill", "--kill-who=main", hco.Service); err != nil {
klog.Errorf("Failed to kill service %s: %v", hco.Service, err)
}
}
default:
// Just kill the service for all other components
return func() {
execCommand(types.CmdTimeout, "systemctl", "kill", "--kill-who=main", hco.Service)
if _, err := execCommand(types.CmdTimeout, "systemctl", "kill", "--kill-who=main", hco.Service); err != nil {
klog.Errorf("Failed to kill service %s: %v", hco.Service, err)
}
}
}
}
Expand Down
8 changes: 6 additions & 2 deletions pkg/problemmetrics/problem_metrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ func TestNewProblem(t *testing.T) {
pmm, fakeProblemCounter, fakeProblemGauge := NewProblemMetricsManagerStub()

for idx, reason := range test.reasons {
pmm.IncrementProblemCounter(reason, test.counts[idx])
if err := pmm.IncrementProblemCounter(reason, test.counts[idx]); err != nil {
t.Errorf("unexpected error: %v", err)
}
}

gotMetrics := append(fakeProblemCounter.ListMetrics(), fakeProblemGauge.ListMetrics()...)
Expand Down Expand Up @@ -266,7 +268,9 @@ func TestSetProblemGauge(t *testing.T) {
pmm, fakeProblemCounter, fakeProblemGauge := NewProblemMetricsManagerStub()

for _, argument := range test.arguments {
pmm.SetProblemGauge(argument.problemType, argument.reason, argument.value)
if err := pmm.SetProblemGauge(argument.problemType, argument.reason, argument.value); err != nil {
t.Errorf("unexpected error: %v", err)
}
}

gotMetrics := append(fakeProblemCounter.ListMetrics(), fakeProblemGauge.ListMetrics()...)
Expand Down
4 changes: 3 additions & 1 deletion pkg/systemlogmonitor/logwatchers/filelog/log_watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,9 @@ const watchPollInterval = 500 * time.Millisecond
// watchLoop is the main watch loop of filelog watcher.
func (s *filelogWatcher) watchLoop() {
defer func() {
s.closer.Close()
if err := s.closer.Close(); err != nil {
klog.Errorf("Failed to close log file: %v", err)
}
close(s.logCh)
s.tomb.Done()
}()
Expand Down
8 changes: 6 additions & 2 deletions pkg/systemlogmonitor/logwatchers/filelog/log_watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,12 @@ Jan 2 03:04:05 kernel: [2.000000] 3
f, err := os.CreateTemp("", "log_watcher_test")
assert.NoError(t, err)
defer func() {
f.Close()
os.Remove(f.Name())
if err := f.Close(); err != nil {
t.Logf("failed to close temporary file %s: %v", f.Name(), err)
}
if err := os.Remove(f.Name()); err != nil {
t.Logf("failed to remove temporary file %s: %v", f.Name(), err)
}
}()
_, err = f.Write([]byte(test.log))
assert.NoError(t, err)
Expand Down
4 changes: 3 additions & 1 deletion pkg/systemlogmonitor/logwatchers/kmsg/log_watcher_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@ func (k *kernelLogWatcher) Watch() (<-chan *logtypes.Log, error) {

// Stop closes the kmsgparser
func (k *kernelLogWatcher) Stop() {
k.kmsgParser.Close()
if err := k.kmsgParser.Close(); err != nil {
klog.Errorf("Failed to close kmsg parser: %v", err)
}
k.tomb.Stop()
}

Expand Down
40 changes: 30 additions & 10 deletions pkg/systemstatsmonitor/cpu_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,34 +187,54 @@ func (cc *cpuCollector) recordUsage() {
}
timersStat := timersStats[0]

cc.mUsageTime.Record(map[string]string{stateLabel: "user"}, clockTick*timersStat.User-cc.lastUsageTime["user"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "user"}, clockTick*timersStat.User-cc.lastUsageTime["user"]); err != nil {
klog.Errorf("Failed to record cpu usage time for user: %v", err)
}
cc.lastUsageTime["user"] = clockTick * timersStat.User

cc.mUsageTime.Record(map[string]string{stateLabel: "system"}, clockTick*timersStat.System-cc.lastUsageTime["system"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "system"}, clockTick*timersStat.System-cc.lastUsageTime["system"]); err != nil {
klog.Errorf("Failed to record cpu usage time for system: %v", err)
}
cc.lastUsageTime["system"] = clockTick * timersStat.System

cc.mUsageTime.Record(map[string]string{stateLabel: "idle"}, clockTick*timersStat.Idle-cc.lastUsageTime["idle"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "idle"}, clockTick*timersStat.Idle-cc.lastUsageTime["idle"]); err != nil {
klog.Errorf("Failed to record cpu usage time for idle: %v", err)
}
cc.lastUsageTime["idle"] = clockTick * timersStat.Idle

cc.mUsageTime.Record(map[string]string{stateLabel: "nice"}, clockTick*timersStat.Nice-cc.lastUsageTime["nice"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "nice"}, clockTick*timersStat.Nice-cc.lastUsageTime["nice"]); err != nil {
klog.Errorf("Failed to record cpu usage time for nice: %v", err)
}
cc.lastUsageTime["nice"] = clockTick * timersStat.Nice

cc.mUsageTime.Record(map[string]string{stateLabel: "iowait"}, clockTick*timersStat.Iowait-cc.lastUsageTime["iowait"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "iowait"}, clockTick*timersStat.Iowait-cc.lastUsageTime["iowait"]); err != nil {
klog.Errorf("Failed to record cpu usage time for iowait: %v", err)
}
cc.lastUsageTime["iowait"] = clockTick * timersStat.Iowait

cc.mUsageTime.Record(map[string]string{stateLabel: "irq"}, clockTick*timersStat.Irq-cc.lastUsageTime["irq"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "irq"}, clockTick*timersStat.Irq-cc.lastUsageTime["irq"]); err != nil {
klog.Errorf("Failed to record cpu usage time for irq: %v", err)
}
cc.lastUsageTime["irq"] = clockTick * timersStat.Irq

cc.mUsageTime.Record(map[string]string{stateLabel: "softirq"}, clockTick*timersStat.Softirq-cc.lastUsageTime["softirq"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "softirq"}, clockTick*timersStat.Softirq-cc.lastUsageTime["softirq"]); err != nil {
klog.Errorf("Failed to record cpu usage time for softirq: %v", err)
}
cc.lastUsageTime["softirq"] = clockTick * timersStat.Softirq

cc.mUsageTime.Record(map[string]string{stateLabel: "steal"}, clockTick*timersStat.Steal-cc.lastUsageTime["steal"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "steal"}, clockTick*timersStat.Steal-cc.lastUsageTime["steal"]); err != nil {
klog.Errorf("Failed to record cpu usage time for steal: %v", err)
}
cc.lastUsageTime["steal"] = clockTick * timersStat.Steal

cc.mUsageTime.Record(map[string]string{stateLabel: "guest"}, clockTick*timersStat.Guest-cc.lastUsageTime["guest"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "guest"}, clockTick*timersStat.Guest-cc.lastUsageTime["guest"]); err != nil {
klog.Errorf("Failed to record cpu usage time for guest: %v", err)
}
cc.lastUsageTime["guest"] = clockTick * timersStat.Guest

cc.mUsageTime.Record(map[string]string{stateLabel: "guest_nice"}, clockTick*timersStat.GuestNice-cc.lastUsageTime["guest_nice"])
if err := cc.mUsageTime.Record(map[string]string{stateLabel: "guest_nice"}, clockTick*timersStat.GuestNice-cc.lastUsageTime["guest_nice"]); err != nil {
klog.Errorf("Failed to record cpu usage time for guest_nice: %v", err)
}
cc.lastUsageTime["guest_nice"] = clockTick * timersStat.GuestNice
}

Expand Down
Loading