Skip to content

Commit 5188a10

Browse files
committed
critest: test metric and metric descriptors
Signed-off-by: Peter Hunt <[email protected]>
1 parent 80b852a commit 5188a10

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

pkg/validate/pod.go

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"os"
2222
"path/filepath"
23+
"strings"
2324

2425
. "github.com/onsi/ginkgo/v2"
2526
. "github.com/onsi/gomega"
@@ -30,6 +31,55 @@ import (
3031
"sigs.k8s.io/cri-tools/pkg/framework"
3132
)
3233

34+
// expectedMetricDescriptorNames contains all expected metric descriptor names
35+
// based on metrics returned by kubelet with CRI-O and cadvisor on the legacy cadvisor stats provider
36+
// on kubernetes 1.35.
37+
var expectedMetricDescriptorNames = []string{
38+
"container_cpu_load_average_10s",
39+
"container_cpu_load_d_average_10s",
40+
"container_cpu_system_seconds_total",
41+
"container_cpu_usage_seconds_total",
42+
"container_cpu_user_seconds_total",
43+
"container_file_descriptors",
44+
"container_fs_inodes_free",
45+
"container_fs_inodes_total",
46+
"container_fs_io_current",
47+
"container_fs_io_time_seconds_total",
48+
"container_fs_io_time_weighted_seconds_total",
49+
"container_fs_limit_bytes",
50+
"container_fs_read_seconds_total",
51+
"container_fs_reads_merged_total",
52+
"container_fs_reads_total",
53+
"container_fs_sector_reads_total",
54+
"container_fs_sector_writes_total",
55+
"container_fs_usage_bytes",
56+
"container_fs_write_seconds_total",
57+
"container_fs_writes_merged_total",
58+
"container_fs_writes_total",
59+
"container_last_seen",
60+
"container_memory_cache",
61+
"container_memory_failcnt",
62+
"container_memory_failures_total",
63+
"container_memory_kernel_usage",
64+
"container_memory_mapped_file",
65+
"container_memory_max_usage_bytes",
66+
"container_memory_rss",
67+
"container_memory_swap",
68+
"container_memory_total_active_file_bytes",
69+
"container_memory_total_inactive_file_bytes",
70+
"container_memory_usage_bytes",
71+
"container_memory_working_set_bytes",
72+
"container_network_receive_bytes_total",
73+
"container_network_receive_errors_total",
74+
"container_network_receive_packets_dropped_total",
75+
"container_network_receive_packets_total",
76+
"container_network_transmit_bytes_total",
77+
"container_network_transmit_errors_total",
78+
"container_network_transmit_packets_dropped_total",
79+
"container_network_transmit_packets_total",
80+
"container_oom_events_total",
81+
}
82+
3383
var _ = framework.KubeDescribe("PodSandbox", func() {
3484
f := framework.NewDefaultCRIFramework()
3585

@@ -80,6 +130,45 @@ var _ = framework.KubeDescribe("PodSandbox", func() {
80130
podID = "" // no need to cleanup pod
81131
})
82132
})
133+
Context("runtime should support metrics operations", func() {
134+
var podID string
135+
var podConfig *runtimeapi.PodSandboxConfig
136+
137+
AfterEach(func() {
138+
if podID != "" {
139+
By("stop PodSandbox")
140+
Expect(rc.StopPodSandbox(context.TODO(), podID)).NotTo(HaveOccurred())
141+
By("delete PodSandbox")
142+
Expect(rc.RemovePodSandbox(context.TODO(), podID)).NotTo(HaveOccurred())
143+
}
144+
})
145+
146+
It("runtime should support returning metrics descriptors [Conformance]", func() {
147+
By("list metric descriptors")
148+
descs := listMetricDescriptors(rc)
149+
150+
By("verify expected metric descriptors are present")
151+
testMetricDescriptors(descs)
152+
})
153+
154+
It("runtime should support listing pod sandbox metrics [Conformance]", func() {
155+
By("create pod sandbox")
156+
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
157+
158+
By("create container in pod")
159+
ic := f.CRIClient.CRIImageClient
160+
containerID := framework.CreatePauseContainer(rc, ic, podID, podConfig, "container-for-metrics-")
161+
162+
By("start container")
163+
startContainer(rc, containerID)
164+
165+
By("list pod sandbox metrics")
166+
metrics := listPodSandboxMetrics(rc)
167+
168+
By("verify pod metrics are present")
169+
testPodSandboxMetrics(metrics, podID)
170+
})
171+
})
83172
})
84173

85174
// podSandboxFound returns whether PodSandbox is found.
@@ -166,6 +255,17 @@ func listPodSandbox(c internalapi.RuntimeService, filter *runtimeapi.PodSandboxF
166255
return pods
167256
}
168257

258+
// listMetricDescriptors lists MetricDescriptors.
259+
func listMetricDescriptors(c internalapi.RuntimeService) []*runtimeapi.MetricDescriptor {
260+
By("List MetricDescriptors.")
261+
262+
descs, err := c.ListMetricDescriptors(context.TODO())
263+
framework.ExpectNoError(err, "failed to list MetricDescriptors status: %v", err)
264+
framework.Logf("List MetricDescriptors succeed")
265+
266+
return descs
267+
}
268+
169269
// createLogTempDir creates the log temp directory for podSandbox.
170270
func createLogTempDir(podSandboxName string) (hostPath, podLogPath string) {
171271
hostPath, err := os.MkdirTemp("", "podLogTest")
@@ -196,3 +296,76 @@ func createPodSandboxWithLogDirectory(c internalapi.RuntimeService) (sandboxID s
196296

197297
return framework.RunPodSandbox(c, podConfig), podConfig, hostPath
198298
}
299+
300+
// testMetricDescriptors verifies that all expected metric descriptors are present.
301+
func testMetricDescriptors(descs []*runtimeapi.MetricDescriptor) {
302+
returnedDescriptors := make(map[string]*runtimeapi.MetricDescriptor)
303+
for _, desc := range descs {
304+
returnedDescriptors[desc.GetName()] = desc
305+
Expect(desc.GetHelp()).NotTo(BeEmpty(), "Metric descriptor %q should have help text", desc.GetName())
306+
Expect(desc.GetLabelKeys()).NotTo(BeEmpty(), "Metric descriptor %q should have label keys", desc.GetName())
307+
}
308+
309+
missingMetrics := []string{}
310+
311+
for _, expectedName := range expectedMetricDescriptorNames {
312+
_, found := returnedDescriptors[expectedName]
313+
if !found {
314+
missingMetrics = append(missingMetrics, expectedName)
315+
}
316+
}
317+
318+
Expect(missingMetrics).To(BeEmpty(), "Expected %s metrics to be present and they were not", strings.Join(missingMetrics, " "))
319+
}
320+
321+
// listPodSandboxMetrics lists PodSandboxMetrics.
322+
func listPodSandboxMetrics(c internalapi.RuntimeService) []*runtimeapi.PodSandboxMetrics {
323+
By("List PodSandboxMetrics.")
324+
325+
metrics, err := c.ListPodSandboxMetrics(context.TODO())
326+
framework.ExpectNoError(err, "failed to list PodSandboxMetrics: %v", err)
327+
framework.Logf("List PodSandboxMetrics succeed")
328+
329+
return metrics
330+
}
331+
332+
// testPodSandboxMetrics verifies that metrics are present for the specified pod.
333+
func testPodSandboxMetrics(allMetrics []*runtimeapi.PodSandboxMetrics, podID string) {
334+
var podMetrics *runtimeapi.PodSandboxMetrics
335+
336+
for _, m := range allMetrics {
337+
if m.GetPodSandboxId() == podID {
338+
podMetrics = m
339+
340+
break
341+
}
342+
}
343+
344+
Expect(podMetrics).NotTo(BeNil(), "Metrics for pod %q should be present", podID)
345+
346+
metricNamesFound := make(map[string]bool)
347+
348+
for _, metric := range podMetrics.GetMetrics() {
349+
if !metricNamesFound[metric.GetName()] {
350+
metricNamesFound[metric.GetName()] = true
351+
}
352+
}
353+
354+
for _, containerMetric := range podMetrics.GetContainerMetrics() {
355+
for _, metric := range containerMetric.GetMetrics() {
356+
if !metricNamesFound[metric.GetName()] {
357+
metricNamesFound[metric.GetName()] = true
358+
}
359+
}
360+
}
361+
362+
missingMetrics := []string{}
363+
364+
for _, expectedName := range expectedMetricDescriptorNames {
365+
if !metricNamesFound[expectedName] {
366+
missingMetrics = append(missingMetrics, expectedName)
367+
}
368+
}
369+
370+
Expect(missingMetrics).To(BeEmpty(), "Expected %s metrics to be present and they were not", strings.Join(missingMetrics, " "))
371+
}

0 commit comments

Comments
 (0)