Skip to content

Commit

Permalink
Merge pull request #541 from jeremyje/windowsservice
Browse files Browse the repository at this point in the history
Enable NPD to run as a Windows Service.
  • Loading branch information
k8s-ci-robot authored Apr 6, 2021
2 parents 1e8008b + a7f78c5 commit fc0edbd
Show file tree
Hide file tree
Showing 34 changed files with 2,877 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
ci.env
pr.env
junit*.xml
debug.test
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ make test
# Run with containerd log monitoring enabled. (Assumes containerd is installed.)
%CD%\bin\windows_amd64\node-problem-detector.exe --logtostderr --enable-k8s-exporter=false --config.system-log-monitor=%CD%\config\windows-containerd-monitor-filelog.json
# Configure NPD to run as a Windows Service
sc.exe create NodeProblemDetector binpath= "%CD%\node-problem-detector.exe [FLAGS]" start= demand
sc.exe failure NodeProblemDetector reset= 0 actions= restart/10000
sc.exe start NodeProblemDetector
```

## Try It Out
Expand Down
21 changes: 10 additions & 11 deletions cmd/nodeproblemdetector/node_problem_detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ limitations under the License.
package main

import (
"os"

"github.com/golang/glog"
"github.com/spf13/pflag"

_ "k8s.io/node-problem-detector/cmd/nodeproblemdetector/exporterplugins"
_ "k8s.io/node-problem-detector/cmd/nodeproblemdetector/problemdaemonplugins"
Expand All @@ -34,15 +31,19 @@ import (
"k8s.io/node-problem-detector/pkg/version"
)

func main() {
npdo := options.NewNodeProblemDetectorOptions()
npdo.AddFlags(pflag.CommandLine)
func npdInteractive(npdo *options.NodeProblemDetectorOptions) {
termCh := make(chan error, 1)
defer close(termCh)

pflag.Parse()
if err := npdMain(npdo, termCh); err != nil {
glog.Fatalf("Problem detector failed with error: %v", err)
}
}

func npdMain(npdo *options.NodeProblemDetectorOptions, termCh <-chan error) error {
if npdo.PrintVersion {
version.PrintVersion()
os.Exit(0)
return nil
}

npdo.SetNodeNameOrDie()
Expand Down Expand Up @@ -78,7 +79,5 @@ func main() {

// Initialize NPD core.
p := problemdetector.NewProblemDetector(problemDaemons, npdExporters)
if err := p.Run(); err != nil {
glog.Fatalf("Problem detector failed with error: %v", err)
}
return p.Run(termCh)
}
30 changes: 30 additions & 0 deletions cmd/nodeproblemdetector/node_problem_detector_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Copyright 2021 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"github.com/spf13/pflag"
"k8s.io/node-problem-detector/cmd/options"
)

func main() {
npdo := options.NewNodeProblemDetectorOptions()
npdo.AddFlags(pflag.CommandLine)

pflag.Parse()
npdInteractive(npdo)
}
133 changes: 133 additions & 0 deletions cmd/nodeproblemdetector/node_problem_detector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
/*
Copyright 2021 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

import (
"errors"
"fmt"
"io/ioutil"
"os"
"strings"
"testing"

_ "k8s.io/node-problem-detector/cmd/nodeproblemdetector/exporterplugins"
_ "k8s.io/node-problem-detector/cmd/nodeproblemdetector/problemdaemonplugins"
"k8s.io/node-problem-detector/cmd/options"
"k8s.io/node-problem-detector/pkg/exporters"
"k8s.io/node-problem-detector/pkg/types"
)

const (
fakeConfigFilePattern = `
{
"plugin": "filelog",
"pluginConfig": {
"timestamp": "^time=\"(\\S*)\"",
"message": "msg=\"([^\n]*)\"",
"timestampFormat": "2006-01-02T15:04:05.999999999-07:00"
},
"logPath": "%s",
"lookback": "5m",
"bufferSize": 10,
"source": "containerd",
"conditions": [],
"rules": [
{
"type": "temporary",
"reason": "MissingPigz",
"pattern": "unpigz not found.*"
},
{
"type": "temporary",
"reason": "IncompatibleContainer",
"pattern": ".*CreateComputeSystem.*"
}
]
}
`
)

func init() {
exporters.Register("nil", types.ExporterHandler{
CreateExporterOrDie: func(types.CommandLineOptions) types.Exporter {
return &nullExporter{}
},
})
}

type nullExporter struct {
}

func (ne *nullExporter) ExportProblems(*types.Status) {
}

func TestNPDMain(t *testing.T) {
npdo, cleanup := setupNPD(t)
defer cleanup()

termCh := make(chan error, 2)
termCh <- errors.New("close")
defer close(termCh)

if err := npdMain(npdo, termCh); err != nil {
t.Errorf("termination signal should not return error got, %v", err)
}
}

func writeTempFile(t *testing.T, ext string, contents string) (string, error) {
f, err := ioutil.TempFile("", "*."+ext)
if err != nil {
return "", fmt.Errorf("cannot create temp file, %v", err)
}

fileName := f.Name()

if err := ioutil.WriteFile(fileName, []byte(contents), 0644); err != nil {
os.Remove(fileName)
return "", fmt.Errorf("cannot write config to temp file %s, %v", fileName, err)
}

return fileName, nil
}

func setupNPD(t *testing.T) (*options.NodeProblemDetectorOptions, func()) {
fakeLogFileName, err := writeTempFile(t, "log", "")
if err != nil {
os.Remove(fakeLogFileName)
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)
t.Fatalf("cannot create temp config file, %v", err)
}

return &options.NodeProblemDetectorOptions{
MonitorConfigPaths: map[types.ProblemDaemonType]*[]string{
"system-log-monitor": {
fakeConfigFileName,
},
},
}, func() {
os.Remove(fakeLogFileName)
os.Remove(fakeConfigFileName)
}
}
Loading

0 comments on commit fc0edbd

Please sign in to comment.