Skip to content

Commit 94b0d3b

Browse files
committed
critest: test metric and metric descriptors
Signed-off-by: Peter Hunt <[email protected]>
1 parent c049207 commit 94b0d3b

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

pkg/validate/pod.go

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

2425
. "github.com/onsi/ginkgo/v2"
2526
. "github.com/onsi/gomega"
27+
"google.golang.org/grpc/codes"
28+
"google.golang.org/grpc/status"
2629
internalapi "k8s.io/cri-api/pkg/apis"
2730
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
2831

2932
"sigs.k8s.io/cri-tools/pkg/common"
3033
"sigs.k8s.io/cri-tools/pkg/framework"
3134
)
3235

36+
// expectedMetricDescriptorNames contains all expected metric descriptor names
37+
// based on metrics returned by kubelet with CRI-O and cadvisor on the legacy cadvisor stats provider
38+
// on kubernetes 1.35.
39+
var expectedMetricDescriptorNames = []string{
40+
"container_blkio_device_usage_total",
41+
"container_cpu_load_average_10s",
42+
"container_cpu_system_seconds_total",
43+
"container_cpu_usage_seconds_total",
44+
"container_cpu_user_seconds_total",
45+
"container_file_descriptors",
46+
"container_fs_reads_bytes_total",
47+
"container_fs_reads_total",
48+
"container_fs_usage_bytes",
49+
"container_fs_writes_bytes_total",
50+
"container_fs_writes_total",
51+
"container_last_seen",
52+
"container_memory_cache",
53+
"container_memory_failcnt",
54+
"container_memory_failures_total",
55+
"container_memory_mapped_file",
56+
"container_memory_max_usage_bytes",
57+
"container_memory_rss",
58+
"container_memory_swap",
59+
"container_memory_usage_bytes",
60+
"container_memory_working_set_bytes",
61+
"container_network_receive_bytes_total",
62+
"container_network_receive_errors_total",
63+
"container_network_receive_packets_dropped_total",
64+
"container_network_receive_packets_total",
65+
"container_network_transmit_bytes_total",
66+
"container_network_transmit_errors_total",
67+
"container_network_transmit_packets_dropped_total",
68+
"container_network_transmit_packets_total",
69+
"container_oom_events_total",
70+
"container_processes",
71+
"container_sockets",
72+
"container_spec_cpu_period",
73+
"container_spec_cpu_shares",
74+
"container_spec_memory_limit_bytes",
75+
"container_spec_memory_reservation_limit_bytes",
76+
"container_spec_memory_swap_limit_bytes",
77+
"container_start_time_seconds",
78+
"container_tasks_state",
79+
"container_threads",
80+
"container_threads_max",
81+
"container_ulimits_soft",
82+
}
83+
3384
var _ = framework.KubeDescribe("PodSandbox", func() {
3485
f := framework.NewDefaultCRIFramework()
3586

@@ -80,6 +131,55 @@ var _ = framework.KubeDescribe("PodSandbox", func() {
80131
podID = "" // no need to cleanup pod
81132
})
82133
})
134+
Context("runtime should support metrics operations", func() {
135+
var podID string
136+
var podConfig *runtimeapi.PodSandboxConfig
137+
BeforeEach(func() {
138+
_, err := rc.ListMetricDescriptors(context.TODO())
139+
if err != nil {
140+
s, ok := status.FromError(err)
141+
Expect(ok && s.Code() == codes.Unimplemented).To(BeTrue(), "Expected CRI metric descriptors call to either be not supported, or not error")
142+
if s.Code() == codes.Unimplemented {
143+
Skip("CRI Metrics endpoints not supported by this runtime version")
144+
}
145+
}
146+
})
147+
148+
AfterEach(func() {
149+
if podID != "" {
150+
By("stop PodSandbox")
151+
Expect(rc.StopPodSandbox(context.TODO(), podID)).NotTo(HaveOccurred())
152+
By("delete PodSandbox")
153+
Expect(rc.RemovePodSandbox(context.TODO(), podID)).NotTo(HaveOccurred())
154+
}
155+
})
156+
157+
It("runtime should support returning metrics descriptors [Conformance]", func() {
158+
By("list metric descriptors")
159+
descs := listMetricDescriptors(rc)
160+
161+
By("verify expected metric descriptors are present")
162+
testMetricDescriptors(descs)
163+
})
164+
165+
It("runtime should support listing pod sandbox metrics [Conformance]", func() {
166+
By("create pod sandbox")
167+
podID, podConfig = framework.CreatePodSandboxForContainer(rc)
168+
169+
By("create container in pod")
170+
ic := f.CRIClient.CRIImageClient
171+
containerID := framework.CreatePauseContainer(rc, ic, podID, podConfig, "container-for-metrics-")
172+
173+
By("start container")
174+
startContainer(rc, containerID)
175+
176+
By("list pod sandbox metrics")
177+
metrics := listPodSandboxMetrics(rc)
178+
179+
By("verify pod metrics are present")
180+
testPodSandboxMetrics(metrics, podID)
181+
})
182+
})
83183
})
84184

85185
// podSandboxFound returns whether PodSandbox is found.
@@ -166,6 +266,17 @@ func listPodSandbox(c internalapi.RuntimeService, filter *runtimeapi.PodSandboxF
166266
return pods
167267
}
168268

269+
// listMetricDescriptors lists MetricDescriptors.
270+
func listMetricDescriptors(c internalapi.RuntimeService) []*runtimeapi.MetricDescriptor {
271+
By("List MetricDescriptors.")
272+
273+
descs, err := c.ListMetricDescriptors(context.TODO())
274+
framework.ExpectNoError(err, "failed to list MetricDescriptors status: %v", err)
275+
framework.Logf("List MetricDescriptors succeed")
276+
277+
return descs
278+
}
279+
169280
// createLogTempDir creates the log temp directory for podSandbox.
170281
func createLogTempDir(podSandboxName string) (hostPath, podLogPath string) {
171282
hostPath, err := os.MkdirTemp("", "podLogTest")
@@ -196,3 +307,76 @@ func createPodSandboxWithLogDirectory(c internalapi.RuntimeService) (sandboxID s
196307

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

0 commit comments

Comments
 (0)