mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-08 03:33:56 +00:00
Merge pull request #117011 from fabi200123/Add-Node-Log-Query-Tests-
Add e2e tests for feature NodeLogQuery
This commit is contained in:
commit
2d9c951abe
@ -17,8 +17,11 @@ limitations under the License.
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -450,4 +453,232 @@ var _ = SIGDescribe("kubelet", func() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Tests for NodeLogQuery feature
|
||||||
|
ginkgo.Describe("kubectl get --raw \"/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=/<insert-log-file-name-here> [Feature:NodeLogQuery]", func() {
|
||||||
|
var (
|
||||||
|
numNodes int
|
||||||
|
nodeNames sets.String
|
||||||
|
)
|
||||||
|
|
||||||
|
ginkgo.BeforeEach(func(ctx context.Context) {
|
||||||
|
nodes, err := e2enode.GetBoundedReadySchedulableNodes(ctx, c, maxNodesToCheck)
|
||||||
|
numNodes = len(nodes.Items)
|
||||||
|
framework.ExpectNoError(err)
|
||||||
|
nodeNames = sets.NewString()
|
||||||
|
for i := 0; i < numNodes; i++ {
|
||||||
|
nodeNames.Insert(nodes.Items[i].Name)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?"
|
||||||
|
returns an error or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the error of running without --query option", func() {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?"
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
_, _, err := framework.StartCmdAndStreamOutput(cmd)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Failed to start kubectl command! Error: %v", err)
|
||||||
|
}
|
||||||
|
err = cmd.Wait()
|
||||||
|
if err == nil {
|
||||||
|
framework.Failf("Command kubectl get --raw" + queryCommand + " was expected to return an error!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet"
|
||||||
|
returns the kubelet logs or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the logs ", func(ctx context.Context) {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?query=kubelet\""
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
assertContains("kubelet", result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&pattern=container"
|
||||||
|
returns something or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the logs filtered by pattern container", func(ctx context.Context) {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?query=kubelet&pattern=container\""
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
assertContains("container", result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&boot=0"
|
||||||
|
returns something or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the kubelet logs for the current boot", func(ctx context.Context) {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?query=kubelet&boot=0\""
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
assertContains("kubelet", result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&boot=-1"
|
||||||
|
returns something or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the kubelet logs for the previous boot", func(ctx context.Context) {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?query=kubelet&boot=-1\""
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
assertContains("kubelet", result)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&tailLines=2"
|
||||||
|
returns something or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the kubelet logs for the previous boot", func(ctx context.Context) {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?query=kubelet&tailLines=3\""
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
logs := journalctlCommand("-u", "kubelet", "-n 3 --utc")
|
||||||
|
if result != 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-node-name-here>/proxy/logs/?query=kubelet&tailLines=2&pattern=kubelet&boot=0"
|
||||||
|
returns something or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the kubelet logs for the current boot with pattern error and output in 2 lines", func(ctx context.Context) {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?query=kubelet&tailLines=3&boot=0&pattern=kubelet\""
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
logs := journalctlCommand("-u", "kubelet", "-n 3 --utc")
|
||||||
|
if result != logs {
|
||||||
|
framework.Failf("Failed to receive the correct kubelet logs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
/*
|
||||||
|
Test if kubectl get --raw "/api/v1/nodes/<insert-node-name-here>/proxy/logs/?query=kubelet&tailLines=3&untilTime=<now>"
|
||||||
|
returns the kubelet logs or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the logs for the requested query until the current date and time", func() {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
start := time.Now().UTC()
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?query=kubelet&tailLines=3&sinceTime=" + start.Format(time.RFC3339) + "\""
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
logs := journalctlCommand("-u", "kubelet", "-n 3 --utc")
|
||||||
|
if result != 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-node-name-here>/proxy/logs/?query=kubelet&tailLines=3&sinceTime=4 hours ago"
|
||||||
|
returns the kubelet logs or not!
|
||||||
|
*/
|
||||||
|
|
||||||
|
ginkgo.It("should return the logs for the requested query since the current date and time", func() {
|
||||||
|
ginkgo.By("Starting the command")
|
||||||
|
start := time.Now().UTC()
|
||||||
|
start = start.Add(time.Duration(-4) * time.Hour)
|
||||||
|
tk := e2ekubectl.NewTestKubeconfig(framework.TestContext.CertDir, framework.TestContext.Host, framework.TestContext.KubeConfig, framework.TestContext.KubeContext, framework.TestContext.KubectlPath, ns)
|
||||||
|
for nodeName := range nodeNames {
|
||||||
|
queryCommand := "\"/api/v1/nodes/" + nodeName + "/proxy/logs/?query=kubelet&tailLines=3&sinceTime=" + start.Format(time.RFC3339) + "\""
|
||||||
|
cmd := tk.KubectlCmd("get", "--raw", queryCommand)
|
||||||
|
result := runKubectlCommand(cmd)
|
||||||
|
logs := journalctlCommand("-u", "kubelet", "--utc")
|
||||||
|
assertContains(result, logs)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
func runKubectlCommand(cmd *exec.Cmd) (result string) {
|
||||||
|
stdout, stderr, err := framework.StartCmdAndStreamOutput(cmd)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Failed to start kubectl command! Stderr: %v, error: %v", stderr, err)
|
||||||
|
}
|
||||||
|
defer stdout.Close()
|
||||||
|
defer stderr.Close()
|
||||||
|
defer framework.TryKill(cmd)
|
||||||
|
|
||||||
|
b_read, err := io.Copy(&buf, stdout)
|
||||||
|
if err != nil {
|
||||||
|
framework.Failf("Expected output from kubectl alpha node-logs %s: %v\n Stderr: %v", cmd.Args, err, stderr)
|
||||||
|
}
|
||||||
|
out := ""
|
||||||
|
if b_read >= 0 {
|
||||||
|
out = buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
framework.Logf("Kubectl output: %s", out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertContains(expectedString string, result string) {
|
||||||
|
if strings.Contains(result, expectedString) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
framework.Failf("Failed to find \"%s\"", expectedString)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func journalctlCommand(arg ...string) string {
|
||||||
|
command := exec.Command("journalctl", arg...)
|
||||||
|
out, err := command.Output()
|
||||||
|
if err != nil {
|
||||||
|
framework.Logf("Command: %v\nError: %v", command, err)
|
||||||
|
framework.Failf("Error at running journalctl command")
|
||||||
|
}
|
||||||
|
framework.Logf("Journalctl output: %s", out)
|
||||||
|
return string(out)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user