mirror of
https://github.com/kubernetes/node-problem-detector.git
synced 2026-08-19 04:06:24 +00:00
Windows Support: Fix Build Regressions, Tests Pass
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Exec creates a new process with the specified arguments.
|
||||
func Exec(name string, arg ...string) *exec.Cmd {
|
||||
// create a process group
|
||||
sysProcAttr := &syscall.SysProcAttr{
|
||||
Setpgid: true,
|
||||
}
|
||||
cmd := exec.Command(name, arg...)
|
||||
cmd.SysProcAttr = sysProcAttr
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Kill the process and subprocesses.
|
||||
func Kill(cmd *exec.Cmd) error {
|
||||
if cmd.Process == nil {
|
||||
return fmt.Errorf("%v does not have a process handle", cmd)
|
||||
}
|
||||
return syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL)
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExec(t *testing.T) {
|
||||
var cmds [][]string
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
cmds = [][]string{
|
||||
{"powershell.exe"},
|
||||
{"cmd.exe", "/C", "echo", "Hello"},
|
||||
{"cmd.exe", "/K", "echo", "Wait", "forever"},
|
||||
{"testdata/hello-world.cmd"},
|
||||
{"testdata/hello-world.bat"},
|
||||
{"testdata/hello-world.ps1"},
|
||||
}
|
||||
} else {
|
||||
cmds = [][]string{
|
||||
{"/bin/sh"},
|
||||
{"/bin/bash"},
|
||||
}
|
||||
}
|
||||
|
||||
for _, v := range cmds {
|
||||
args := v
|
||||
t.Run(fmt.Sprintf("%v", args), func(t *testing.T) {
|
||||
cmd := Exec(args[0], args[1:]...)
|
||||
|
||||
if err := Kill(cmd); err == nil {
|
||||
t.Error("Kill(cmd) expected to have error because of empty handle, got none")
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
t.Errorf("Start() got error, %v", err)
|
||||
}
|
||||
|
||||
if err := Kill(cmd); err != nil {
|
||||
t.Errorf("Kill(cmd) for %s %v got error, %v", cmd.Path, cmd.Args, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Exec creates a new process with the specified arguments.
|
||||
func Exec(name string, arg ...string) *exec.Cmd {
|
||||
// Windows does not handle relative path names in exec very well.
|
||||
name = filepath.Clean(name)
|
||||
cmdArgs := arg
|
||||
|
||||
// Detect scripts via file extension and automatically invoke them within a shell.
|
||||
// This mirrors the Linux behavior if the execute bit on file where a shell context
|
||||
// is automatically created.
|
||||
switch strings.ToLower(filepath.Ext(name)) {
|
||||
// Batch Scripts
|
||||
case ".cmd", ".bat":
|
||||
cmdArgs = append([]string{"/C", name}, cmdArgs...)
|
||||
name = "cmd.exe"
|
||||
// Powershell Scripts
|
||||
case ".ps1":
|
||||
cmdArgs = append([]string{"-NoLogo", "-NoProfile", "-NonInteractive", "-ExecutionPolicy", "RemoteSigned", name}, cmdArgs...)
|
||||
name = "powershell.exe"
|
||||
default:
|
||||
// Run directly.
|
||||
}
|
||||
|
||||
return exec.Command(name, cmdArgs...)
|
||||
}
|
||||
|
||||
// ExitStatus returns the exit code of the application.
|
||||
func ExitStatus(cmd *exec.Cmd) int {
|
||||
return cmd.ProcessState.Sys().(syscall.WaitStatus).ExitStatus()
|
||||
}
|
||||
|
||||
// Kill the process and subprocesses.
|
||||
func Kill(cmd *exec.Cmd) error {
|
||||
if cmd.Process == nil {
|
||||
return fmt.Errorf("%v does not have a process handle", cmd)
|
||||
}
|
||||
|
||||
// Use taskkill to kill the child process by process id.
|
||||
// /F = Force
|
||||
// /T = Kill child processes.
|
||||
// https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/taskkill
|
||||
kill := exec.Command("TASKKILL", "/T", "/F", "/PID", strconv.Itoa(cmd.Process.Pid))
|
||||
kill.Stderr = os.Stderr
|
||||
kill.Stdout = os.Stdout
|
||||
err := kill.Run()
|
||||
if execErr, ok := err.(*exec.ExitError); ok {
|
||||
// Error code 128 (ERROR_WAIT_NO_CHILDREN) means that taskkill couldn't find the process, it probably died already.
|
||||
// https://docs.microsoft.com/en-us/windows/win32/debug/system-error-codes--0-499-
|
||||
if execErr.ExitCode() == 128 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -71,6 +71,7 @@ func ParsePrometheusMetrics(metricsText string) ([]Float64MetricRepresentation,
|
||||
var metrics []Float64MetricRepresentation
|
||||
|
||||
var textParser expfmt.TextParser
|
||||
metricsText = strings.ReplaceAll(metricsText, "\r", "")
|
||||
metricFamilies, err := textParser.TextToMetricFamilies(strings.NewReader(metricsText))
|
||||
if err != nil {
|
||||
return metrics, err
|
||||
|
||||
@@ -63,7 +63,7 @@ func TestPrometheusMetricsParsingAndMatching(t *testing.T) {
|
||||
Name: "host_uptime",
|
||||
Labels: map[string]string{"kernel_version": "mismatched-version"},
|
||||
},
|
||||
// Non-exsistant metric.
|
||||
// Non-existant metric.
|
||||
{
|
||||
Name: "host_downtime",
|
||||
Labels: map[string]string{},
|
||||
@@ -109,7 +109,7 @@ func TestPrometheusMetricsParsingAndMatching(t *testing.T) {
|
||||
Name: "host_uptime",
|
||||
Labels: map[string]string{"kernel_version": "mismatched-version"},
|
||||
},
|
||||
// Non-exsistant metric.
|
||||
// Non-existant metric.
|
||||
{
|
||||
Name: "host_downtime",
|
||||
Labels: map[string]string{},
|
||||
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
echo Hello World
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
@echo off
|
||||
echo Hello World
|
||||
+1
@@ -0,0 +1 @@
|
||||
Write-Host "Hello World"
|
||||
Reference in New Issue
Block a user