mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-04 18:00:08 +00:00
e2e: add NodeLogQuery tests for Windows nodes
This commit is contained in:
parent
8ba29970e6
commit
66ea02684b
@ -23,6 +23,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -457,21 +458,32 @@ var _ = SIGDescribe("kubelet", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Tests for NodeLogQuery feature
|
// Tests for NodeLogQuery feature
|
||||||
f.Describe("kubectl get --raw \"/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=/<insert-log-file-name-here>", feature.NodeLogQuery, "[LinuxOnly]", func() {
|
f.Describe("kubectl get --raw \"/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=/<insert-log-file-name-here>", feature.NodeLogQuery, func() {
|
||||||
var linuxNodeName string
|
var linuxNodeName string
|
||||||
|
var windowsNodeName string
|
||||||
|
|
||||||
ginkgo.BeforeEach(func(ctx context.Context) {
|
ginkgo.BeforeEach(func(ctx context.Context) {
|
||||||
nodes, err := e2enode.GetReadyNodesIncludingTainted(ctx, c)
|
allNodes, err := e2enode.GetReadyNodesIncludingTainted(ctx, c)
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
if len(nodes.Items) == 0 {
|
if len(allNodes.Items) == 0 {
|
||||||
framework.Fail("Expected at least one node to be present")
|
framework.Fail("Expected at least one node to be present")
|
||||||
}
|
}
|
||||||
|
// Make a copy of the node list as getLinuxNodes will filter out the Windows nodes
|
||||||
|
nodes := allNodes.DeepCopy()
|
||||||
|
|
||||||
linuxNodes := getLinuxNodes(nodes)
|
linuxNodes := getLinuxNodes(nodes)
|
||||||
if len(linuxNodes.Items) == 0 {
|
if len(linuxNodes.Items) == 0 {
|
||||||
framework.Fail("Expected at least one Linux node to be present")
|
framework.Fail("Expected at least one Linux node to be present")
|
||||||
}
|
}
|
||||||
|
linuxNodeName = linuxNodes.Items[0].Name
|
||||||
|
|
||||||
|
windowsNodes := getWindowsNodes(allNodes)
|
||||||
|
if len(windowsNodes.Items) == 0 {
|
||||||
|
framework.Logf("No Windows node found")
|
||||||
|
} else {
|
||||||
|
windowsNodeName = windowsNodes.Items[0].Name
|
||||||
|
}
|
||||||
|
|
||||||
linuxNodeName = nodes.Items[0].Name
|
|
||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -494,7 +506,7 @@ var _ = SIGDescribe("kubelet", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet"
|
Test if kubectl get --raw "/api/v1/nodes/<insert-linux-node-name-here>/proxy/logs/?query=kubelet"
|
||||||
returns the kubelet logs
|
returns the kubelet logs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -509,7 +521,7 @@ var _ = SIGDescribe("kubelet", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&boot=0"
|
Test if kubectl get --raw "/api/v1/nodes/<insert-linux-node-name-here>/proxy/logs/?query=kubelet&boot=0"
|
||||||
returns kubelet logs from the current boot
|
returns kubelet logs from the current boot
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -524,7 +536,7 @@ var _ = SIGDescribe("kubelet", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&tailLines=3"
|
Test if kubectl get --raw "/api/v1/nodes/<insert-linux-node-name-here>/proxy/logs/?query=kubelet&tailLines=3"
|
||||||
returns the last three lines of the kubelet log
|
returns the last three lines of the kubelet log
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -543,7 +555,7 @@ var _ = SIGDescribe("kubelet", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&pattern=kubelet"
|
Test if kubectl get --raw "/api/v1/nodes/<insert-linux-node-name-here>/proxy/logs/?query=kubelet&pattern=container"
|
||||||
returns kubelet logs for the current boot with the pattern container
|
returns kubelet logs for the current boot with the pattern container
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -562,8 +574,8 @@ var _ = SIGDescribe("kubelet", func() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&sinceTime=<now>"
|
Test if kubectl get --raw "/api/v1/nodes/<insert-linux-node-name-here>/proxy/logs/?query=kubelet&sinceTime=<now>"
|
||||||
returns the kubelet since the current date and time. This can be "-- No entries --" which is correct.
|
returns the kubelet logs since the current date and time. This can be "-- No entries --" which is correct.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ginkgo.It("should return the kubelet logs since the current date and time", func() {
|
ginkgo.It("should return the kubelet logs since the current date and time", func() {
|
||||||
@ -581,22 +593,93 @@ var _ = SIGDescribe("kubelet", func() {
|
|||||||
framework.Failf("Failed to receive the correct kubelet logs or the correct amount of lines of logs")
|
framework.Failf("Failed to receive the correct kubelet logs or the correct amount of lines of logs")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-windows-node-name-here>/proxy/logs/?query="Microsoft-Windows-Security-SPP"
|
||||||
|
returns the Microsoft-Windows-Security-SPP log
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the Microsoft-Windows-Security-SPP logs", func(ctx context.Context) {
|
||||||
|
if len(windowsNodeName) == 0 {
|
||||||
|
ginkgo.Skip("No Windows node found")
|
||||||
|
}
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
|
||||||
|
queryCommand := fmt.Sprintf("/api/v1/nodes/%s/proxy/logs/?query=Microsoft-Windows-Security-SPP", windowsNodeName)
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
assertContains("ProviderName: Microsoft-Windows-Security-SPP", result)
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-windows-node-name-here>/proxy/logs/?query=Microsoft-Windows-Security-SPP&tailLines=3"
|
||||||
|
returns the last three lines of the Microsoft-Windows-Security-SPP log
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the last three lines of the Microsoft-Windows-Security-SPP logs", func(ctx context.Context) {
|
||||||
|
e2eskipper.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
|
||||||
|
if len(windowsNodeName) == 0 {
|
||||||
|
ginkgo.Skip("No Windows node found")
|
||||||
|
}
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
|
||||||
|
queryCommand := fmt.Sprintf("/api/v1/nodes/%s/proxy/logs/?query=Microsoft-Windows-Security-SPP&tailLines=3", windowsNodeName)
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
logs := getWinEventCommandOnNode(windowsNodeName, "Microsoft-Windows-Security-SPP", " -MaxEvents 3")
|
||||||
|
if trimSpaceNewlineInString(result) != trimSpaceNewlineInString(logs) {
|
||||||
|
framework.Failf("Failed to receive the correct Microsoft-Windows-Security-SPP logs or the correct amount of lines of logs")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-windows-node-name-here>/proxy/logs/?query=Microsoft-Windows-Security-SPP&pattern=Health"
|
||||||
|
returns the lines of the Microsoft-Windows-Security-SPP log with the pattern Health
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the Microsoft-Windows-Security-SPP logs with the pattern Health", func(ctx context.Context) {
|
||||||
|
e2eskipper.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
|
||||||
|
if len(windowsNodeName) == 0 {
|
||||||
|
ginkgo.Skip("No Windows node found")
|
||||||
|
}
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
|
||||||
|
queryCommand := fmt.Sprintf("/api/v1/nodes/%s/proxy/logs/?query=Microsoft-Windows-Security-SPP&pattern=Health", windowsNodeName)
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
logs := getWinEventCommandOnNode(windowsNodeName, "Microsoft-Windows-Security-SPP", " | Where-Object -Property Message -Match Health")
|
||||||
|
if trimSpaceNewlineInString(result) != trimSpaceNewlineInString(logs) {
|
||||||
|
framework.Failf("Failed to receive the correct Microsoft-Windows-Security-SPP logs or the correct amount of lines of logs")
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
func getLinuxNodes(nodes *v1.NodeList) *v1.NodeList {
|
func getLinuxNodes(nodes *v1.NodeList) *v1.NodeList {
|
||||||
e2enode.Filter(nodes, func(node v1.Node) bool {
|
filteredNodes := nodes
|
||||||
return isLinuxNode(&node)
|
e2enode.Filter(filteredNodes, func(node v1.Node) bool {
|
||||||
|
return isNode(&node, "linux")
|
||||||
})
|
})
|
||||||
return nodes
|
return filteredNodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func isLinuxNode(node *v1.Node) bool {
|
func getWindowsNodes(nodes *v1.NodeList) *v1.NodeList {
|
||||||
|
filteredNodes := nodes
|
||||||
|
e2enode.Filter(filteredNodes, func(node v1.Node) bool {
|
||||||
|
return isNode(&node, "windows")
|
||||||
|
})
|
||||||
|
return filteredNodes
|
||||||
|
}
|
||||||
|
|
||||||
|
func isNode(node *v1.Node, os string) bool {
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if os, found := node.Labels[v1.LabelOSStable]; found {
|
if foundOS, found := node.Labels[v1.LabelOSStable]; found {
|
||||||
return (os == "linux")
|
return (os == foundOS)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -631,10 +714,26 @@ func assertContains(expectedString string, result string) {
|
|||||||
framework.Failf("Failed to find \"%s\"", expectedString)
|
framework.Failf("Failed to find \"%s\"", expectedString)
|
||||||
}
|
}
|
||||||
|
|
||||||
func journalctlCommandOnNode(nodeName string, args string) string {
|
func commandOnNode(nodeName string, cmd string) string {
|
||||||
result, err := e2essh.NodeExec(context.Background(), nodeName,
|
result, err := e2essh.NodeExec(context.Background(), nodeName, cmd, framework.TestContext.Provider)
|
||||||
"journalctl --utc --no-pager --output=short-precise "+args, framework.TestContext.Provider)
|
|
||||||
framework.ExpectNoError(err)
|
framework.ExpectNoError(err)
|
||||||
e2essh.LogResult(result)
|
e2essh.LogResult(result)
|
||||||
return result.Stdout
|
return result.Stdout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func journalctlCommandOnNode(nodeName string, args string) string {
|
||||||
|
return commandOnNode(nodeName, "journalctl --utc --no-pager --output=short-precise "+args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getWinEventCommandOnNode(nodeName string, providerName, args string) string {
|
||||||
|
output := commandOnNode(nodeName, "Get-WinEvent -FilterHashtable @{LogName='Application'; ProviderName='"+providerName+"'}"+args+" | Sort-Object TimeCreated | Format-Table -AutoSize -Wrap")
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
func trimSpaceNewlineInString(s string) string {
|
||||||
|
// Remove Windows newlines
|
||||||
|
re := regexp.MustCompile(` +\r?\n +`)
|
||||||
|
s = re.ReplaceAllString(s, "")
|
||||||
|
// Replace spaces to account for cases like "\r\n " that could lead to false negatives
|
||||||
|
return strings.ReplaceAll(s, " ", "")
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user