1
16
17 package stats
18
19 import (
20 "context"
21 "fmt"
22 "testing"
23 "time"
24
25 "github.com/golang/mock/gomock"
26 cadvisorapiv1 "github.com/google/cadvisor/info/v1"
27 cadvisorapiv2 "github.com/google/cadvisor/info/v2"
28 fuzz "github.com/google/gofuzz"
29 "github.com/stretchr/testify/assert"
30 "github.com/stretchr/testify/require"
31
32 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
33 "k8s.io/apimachinery/pkg/types"
34 statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
35 cadvisortest "k8s.io/kubernetes/pkg/kubelet/cadvisor/testing"
36 kubecontainertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
37 kubepodtest "k8s.io/kubernetes/pkg/kubelet/pod/testing"
38 serverstats "k8s.io/kubernetes/pkg/kubelet/server/stats"
39 "k8s.io/kubernetes/pkg/volume"
40 )
41
42 const (
43
44 offsetCPUUsageCores = iota
45 offsetCPUUsageCoreSeconds
46 offsetMemPageFaults
47 offsetMemMajorPageFaults
48 offsetMemUsageBytes
49 offsetMemRSSBytes
50 offsetMemWorkingSetBytes
51 offsetNetRxBytes
52 offsetNetRxErrors
53 offsetNetTxBytes
54 offsetNetTxErrors
55 offsetFsCapacity
56 offsetFsAvailable
57 offsetFsUsage
58 offsetFsInodes
59 offsetFsInodesFree
60 offsetFsTotalUsageBytes
61 offsetFsBaseUsageBytes
62 offsetFsInodeUsage
63 offsetAcceleratorDutyCycle
64 offsetMemSwapUsageBytes
65 )
66
67 var (
68 timestamp = time.Now()
69 creationTime = timestamp.Add(-5 * time.Minute)
70 )
71
72 func TestGetCgroupStats(t *testing.T) {
73 const (
74 cgroupName = "test-cgroup-name"
75 containerInfoSeed = 1000
76 updateStats = false
77 )
78
79 mockCtrl := gomock.NewController(t)
80 defer mockCtrl.Finish()
81
82 var (
83 mockCadvisor = cadvisortest.NewMockInterface(mockCtrl)
84 mockPodManager = new(kubepodtest.MockManager)
85 mockRuntimeCache = new(kubecontainertest.MockRuntimeCache)
86
87 assert = assert.New(t)
88 options = cadvisorapiv2.RequestOptions{IdType: cadvisorapiv2.TypeName, Count: 2, Recursive: false}
89
90 containerInfo = getTestContainerInfo(containerInfoSeed, "test-pod", "test-ns", "test-container")
91 containerInfoMap = map[string]cadvisorapiv2.ContainerInfo{cgroupName: containerInfo}
92 )
93
94 mockCadvisor.EXPECT().ContainerInfoV2(cgroupName, options).Return(containerInfoMap, nil)
95
96 provider := newStatsProvider(mockCadvisor, mockPodManager, mockRuntimeCache, fakeContainerStatsProvider{})
97 cs, ns, err := provider.GetCgroupStats(cgroupName, updateStats)
98 assert.NoError(err)
99
100 checkCPUStats(t, "", containerInfoSeed, cs.CPU)
101 checkMemoryStats(t, "", containerInfoSeed, containerInfo, cs.Memory)
102 checkNetworkStats(t, "", containerInfoSeed, ns)
103 checkSwapStats(t, "", containerInfoSeed, containerInfo, cs.Swap)
104
105 assert.Equal(cgroupName, cs.Name)
106 assert.Equal(metav1.NewTime(containerInfo.Spec.CreationTime), cs.StartTime)
107 }
108
109 func TestGetCgroupCPUAndMemoryStats(t *testing.T) {
110 const (
111 cgroupName = "test-cgroup-name"
112 containerInfoSeed = 1000
113 updateStats = false
114 )
115
116 mockCtrl := gomock.NewController(t)
117 defer mockCtrl.Finish()
118
119 var (
120 mockCadvisor = cadvisortest.NewMockInterface(mockCtrl)
121 mockPodManager = new(kubepodtest.MockManager)
122 mockRuntimeCache = new(kubecontainertest.MockRuntimeCache)
123
124 assert = assert.New(t)
125 options = cadvisorapiv2.RequestOptions{IdType: cadvisorapiv2.TypeName, Count: 2, Recursive: false}
126
127 containerInfo = getTestContainerInfo(containerInfoSeed, "test-pod", "test-ns", "test-container")
128 containerInfoMap = map[string]cadvisorapiv2.ContainerInfo{cgroupName: containerInfo}
129 )
130
131 mockCadvisor.EXPECT().ContainerInfoV2(cgroupName, options).Return(containerInfoMap, nil)
132
133 provider := newStatsProvider(mockCadvisor, mockPodManager, mockRuntimeCache, fakeContainerStatsProvider{})
134 cs, err := provider.GetCgroupCPUAndMemoryStats(cgroupName, updateStats)
135 assert.NoError(err)
136
137 checkCPUStats(t, "", containerInfoSeed, cs.CPU)
138 checkMemoryStats(t, "", containerInfoSeed, containerInfo, cs.Memory)
139
140 assert.Equal(cgroupName, cs.Name)
141 assert.Equal(metav1.NewTime(containerInfo.Spec.CreationTime), cs.StartTime)
142 }
143
144 func TestRootFsStats(t *testing.T) {
145 const (
146 rootFsInfoSeed = 1000
147 containerInfoSeed = 2000
148 )
149
150 mockCtrl := gomock.NewController(t)
151 defer mockCtrl.Finish()
152
153 var (
154 mockCadvisor = cadvisortest.NewMockInterface(mockCtrl)
155 mockPodManager = new(kubepodtest.MockManager)
156 mockRuntimeCache = new(kubecontainertest.MockRuntimeCache)
157
158 assert = assert.New(t)
159 options = cadvisorapiv2.RequestOptions{IdType: cadvisorapiv2.TypeName, Count: 2, Recursive: false}
160
161 rootFsInfo = getTestFsInfo(rootFsInfoSeed)
162 containerInfo = getTestContainerInfo(containerInfoSeed, "test-pod", "test-ns", "test-container")
163 containerInfoMap = map[string]cadvisorapiv2.ContainerInfo{"/": containerInfo}
164 )
165
166 mockCadvisor.EXPECT().RootFsInfo().Return(rootFsInfo, nil)
167 mockCadvisor.EXPECT().ContainerInfoV2("/", options).Return(containerInfoMap, nil)
168
169 provider := newStatsProvider(mockCadvisor, mockPodManager, mockRuntimeCache, fakeContainerStatsProvider{})
170 stats, err := provider.RootFsStats()
171 assert.NoError(err)
172
173 checkFsStats(t, "", rootFsInfoSeed, stats)
174
175 assert.Equal(metav1.NewTime(containerInfo.Stats[0].Timestamp), stats.Time)
176 assert.Equal(rootFsInfo.Usage, *stats.UsedBytes)
177 assert.Equal(*rootFsInfo.Inodes-*rootFsInfo.InodesFree, *stats.InodesUsed)
178 }
179
180 func TestHasDedicatedImageFs(t *testing.T) {
181 ctx := context.Background()
182 mockCtrl := gomock.NewController(t)
183 defer mockCtrl.Finish()
184 imageStatsExpected := &statsapi.FsStats{AvailableBytes: uint64Ptr(1)}
185
186 for desc, test := range map[string]struct {
187 rootfsDevice string
188 imagefsDevice string
189 dedicated bool
190 imageFsStats *statsapi.FsStats
191 containerFsStats *statsapi.FsStats
192 }{
193 "dedicated device for image filesystem": {
194 rootfsDevice: "root/device",
195 imagefsDevice: "image/device",
196 dedicated: true,
197 imageFsStats: imageStatsExpected,
198 },
199 "shared device for image filesystem": {
200 rootfsDevice: "share/device",
201 imagefsDevice: "share/device",
202 dedicated: false,
203 imageFsStats: imageStatsExpected,
204 containerFsStats: imageStatsExpected,
205 },
206 "split filesystem for images": {
207 rootfsDevice: "root/device",
208 imagefsDevice: "root/device",
209 dedicated: true,
210 imageFsStats: &statsapi.FsStats{AvailableBytes: uint64Ptr(1)},
211 containerFsStats: &statsapi.FsStats{AvailableBytes: uint64Ptr(2)},
212 },
213 } {
214 t.Logf("TestCase %q", desc)
215 var (
216 mockCadvisor = cadvisortest.NewMockInterface(mockCtrl)
217 mockPodManager = new(kubepodtest.MockManager)
218 mockRuntimeCache = new(kubecontainertest.MockRuntimeCache)
219 )
220 mockCadvisor.EXPECT().RootFsInfo().Return(cadvisorapiv2.FsInfo{Device: test.rootfsDevice}, nil)
221 provider := newStatsProvider(mockCadvisor, mockPodManager, mockRuntimeCache, fakeContainerStatsProvider{
222 device: test.imagefsDevice,
223 imageFs: test.imageFsStats,
224 containerFs: test.containerFsStats,
225 })
226
227 dedicated, err := provider.HasDedicatedImageFs(ctx)
228 assert.NoError(t, err)
229 assert.Equal(t, test.dedicated, dedicated)
230 }
231 }
232
233 func getTerminatedContainerInfo(seed int, podName string, podNamespace string, containerName string) cadvisorapiv2.ContainerInfo {
234 cinfo := getTestContainerInfo(seed, podName, podNamespace, containerName)
235 cinfo.Stats[0].Memory.RSS = 0
236 cinfo.Stats[0].CpuInst.Usage.Total = 0
237 cinfo.Stats[0].Network = &cadvisorapiv2.NetworkStats{
238 Interfaces: []cadvisorapiv1.InterfaceStats{{
239 Name: "eth0",
240 RxBytes: 0,
241 RxErrors: 0,
242 TxBytes: 0,
243 TxErrors: 0,
244 }, {
245 Name: "cbr0",
246 RxBytes: 0,
247 RxErrors: 0,
248 TxBytes: 0,
249 TxErrors: 0,
250 }},
251 }
252 return cinfo
253 }
254
255 func getContainerInfoWithZeroCpuMem(seed int, podName string, podNamespace string, containerName string) cadvisorapiv2.ContainerInfo {
256 cinfo := getTestContainerInfo(seed, podName, podNamespace, containerName)
257 cinfo.Stats[0].Memory.RSS = 0
258 cinfo.Stats[0].CpuInst.Usage.Total = 0
259 return cinfo
260 }
261
262 func getTestContainerInfo(seed int, podName string, podNamespace string, containerName string) cadvisorapiv2.ContainerInfo {
263 labels := map[string]string{}
264 if podName != "" {
265 labels = map[string]string{
266 "io.kubernetes.pod.name": podName,
267 "io.kubernetes.pod.uid": "UID" + podName,
268 "io.kubernetes.pod.namespace": podNamespace,
269 "io.kubernetes.container.name": containerName,
270 }
271 }
272
273 unlimitedMemory := uint64(1 << 63)
274 spec := cadvisorapiv2.ContainerSpec{
275 CreationTime: testTime(creationTime, seed),
276 HasCpu: true,
277 HasMemory: true,
278 HasNetwork: true,
279 Labels: labels,
280 Memory: cadvisorapiv2.MemorySpec{
281 Limit: unlimitedMemory,
282 SwapLimit: unlimitedMemory,
283 },
284 CustomMetrics: generateCustomMetricSpec(),
285 }
286
287 totalUsageBytes := uint64(seed + offsetFsTotalUsageBytes)
288 baseUsageBytes := uint64(seed + offsetFsBaseUsageBytes)
289 inodeUsage := uint64(seed + offsetFsInodeUsage)
290
291 stats := cadvisorapiv2.ContainerStats{
292 Timestamp: testTime(timestamp, seed),
293 Cpu: &cadvisorapiv1.CpuStats{},
294 CpuInst: &cadvisorapiv2.CpuInstStats{},
295 Memory: &cadvisorapiv1.MemoryStats{
296 Usage: uint64(seed + offsetMemUsageBytes),
297 WorkingSet: uint64(seed + offsetMemWorkingSetBytes),
298 RSS: uint64(seed + offsetMemRSSBytes),
299 ContainerData: cadvisorapiv1.MemoryStatsMemoryData{
300 Pgfault: uint64(seed + offsetMemPageFaults),
301 Pgmajfault: uint64(seed + offsetMemMajorPageFaults),
302 },
303 Swap: uint64(seed + offsetMemSwapUsageBytes),
304 },
305 Network: &cadvisorapiv2.NetworkStats{
306 Interfaces: []cadvisorapiv1.InterfaceStats{{
307 Name: "eth0",
308 RxBytes: uint64(seed + offsetNetRxBytes),
309 RxErrors: uint64(seed + offsetNetRxErrors),
310 TxBytes: uint64(seed + offsetNetTxBytes),
311 TxErrors: uint64(seed + offsetNetTxErrors),
312 }, {
313 Name: "cbr0",
314 RxBytes: 100,
315 RxErrors: 100,
316 TxBytes: 100,
317 TxErrors: 100,
318 }},
319 },
320 CustomMetrics: generateCustomMetrics(spec.CustomMetrics),
321 Filesystem: &cadvisorapiv2.FilesystemStats{
322 TotalUsageBytes: &totalUsageBytes,
323 BaseUsageBytes: &baseUsageBytes,
324 InodeUsage: &inodeUsage,
325 },
326 Accelerators: []cadvisorapiv1.AcceleratorStats{
327 {
328 Make: "nvidia",
329 Model: "Tesla K80",
330 ID: "foobar",
331 MemoryTotal: uint64(seed + offsetMemUsageBytes),
332 MemoryUsed: uint64(seed + offsetMemUsageBytes),
333 DutyCycle: uint64(seed + offsetAcceleratorDutyCycle),
334 },
335 },
336 }
337 stats.Cpu.Usage.Total = uint64(seed + offsetCPUUsageCoreSeconds)
338 stats.CpuInst.Usage.Total = uint64(seed + offsetCPUUsageCores)
339 return cadvisorapiv2.ContainerInfo{
340 Spec: spec,
341 Stats: []*cadvisorapiv2.ContainerStats{&stats},
342 }
343 }
344
345 func getTestFsInfo(seed int) cadvisorapiv2.FsInfo {
346 var (
347 inodes = uint64(seed + offsetFsInodes)
348 inodesFree = uint64(seed + offsetFsInodesFree)
349 )
350 return cadvisorapiv2.FsInfo{
351 Timestamp: time.Now(),
352 Device: "test-device",
353 Mountpoint: "test-mount-point",
354 Capacity: uint64(seed + offsetFsCapacity),
355 Available: uint64(seed + offsetFsAvailable),
356 Usage: uint64(seed + offsetFsUsage),
357 Inodes: &inodes,
358 InodesFree: &inodesFree,
359 }
360 }
361
362 func getPodVolumeStats(seed int, volumeName string) statsapi.VolumeStats {
363 availableBytes := uint64(seed + offsetFsAvailable)
364 capacityBytes := uint64(seed + offsetFsCapacity)
365 usedBytes := uint64(seed + offsetFsUsage)
366 inodes := uint64(seed + offsetFsInodes)
367 inodesFree := uint64(seed + offsetFsInodesFree)
368 inodesUsed := uint64(seed + offsetFsInodeUsage)
369 fsStats := statsapi.FsStats{
370 Time: metav1.NewTime(time.Now()),
371 AvailableBytes: &availableBytes,
372 CapacityBytes: &capacityBytes,
373 UsedBytes: &usedBytes,
374 Inodes: &inodes,
375 InodesFree: &inodesFree,
376 InodesUsed: &inodesUsed,
377 }
378 return statsapi.VolumeStats{
379 FsStats: fsStats,
380 Name: volumeName,
381 }
382 }
383
384 func generateCustomMetricSpec() []cadvisorapiv1.MetricSpec {
385 f := fuzz.New().NilChance(0).Funcs(
386 func(e *cadvisorapiv1.MetricSpec, c fuzz.Continue) {
387 c.Fuzz(&e.Name)
388 switch c.Intn(3) {
389 case 0:
390 e.Type = cadvisorapiv1.MetricGauge
391 case 1:
392 e.Type = cadvisorapiv1.MetricCumulative
393 case 2:
394 e.Type = cadvisorapiv1.MetricType("delta")
395 }
396 switch c.Intn(2) {
397 case 0:
398 e.Format = cadvisorapiv1.IntType
399 case 1:
400 e.Format = cadvisorapiv1.FloatType
401 }
402 c.Fuzz(&e.Units)
403 })
404 var ret []cadvisorapiv1.MetricSpec
405 f.Fuzz(&ret)
406 return ret
407 }
408
409 func generateCustomMetrics(spec []cadvisorapiv1.MetricSpec) map[string][]cadvisorapiv1.MetricVal {
410 ret := map[string][]cadvisorapiv1.MetricVal{}
411 for _, metricSpec := range spec {
412 f := fuzz.New().NilChance(0).Funcs(
413 func(e *cadvisorapiv1.MetricVal, c fuzz.Continue) {
414 switch metricSpec.Format {
415 case cadvisorapiv1.IntType:
416 c.Fuzz(&e.IntValue)
417 case cadvisorapiv1.FloatType:
418 c.Fuzz(&e.FloatValue)
419 }
420 })
421
422 var metrics []cadvisorapiv1.MetricVal
423 f.Fuzz(&metrics)
424 ret[metricSpec.Name] = metrics
425 }
426 return ret
427 }
428
429 func testTime(base time.Time, seed int) time.Time {
430 return base.Add(time.Duration(seed) * time.Second)
431 }
432
433 func checkNetworkStats(t *testing.T, label string, seed int, stats *statsapi.NetworkStats) {
434 assert.NotNil(t, stats)
435 assert.EqualValues(t, testTime(timestamp, seed).Unix(), stats.Time.Time.Unix(), label+".Net.Time")
436 assert.EqualValues(t, "eth0", stats.Name, "default interface name is not eth0")
437 assert.EqualValues(t, seed+offsetNetRxBytes, *stats.RxBytes, label+".Net.RxBytes")
438 assert.EqualValues(t, seed+offsetNetRxErrors, *stats.RxErrors, label+".Net.RxErrors")
439 assert.EqualValues(t, seed+offsetNetTxBytes, *stats.TxBytes, label+".Net.TxBytes")
440 assert.EqualValues(t, seed+offsetNetTxErrors, *stats.TxErrors, label+".Net.TxErrors")
441
442 assert.EqualValues(t, 2, len(stats.Interfaces), "network interfaces should contain 2 elements")
443
444 assert.EqualValues(t, "eth0", stats.Interfaces[0].Name, "default interface name is not eth0")
445 assert.EqualValues(t, seed+offsetNetRxBytes, *stats.Interfaces[0].RxBytes, label+".Net.TxErrors")
446 assert.EqualValues(t, seed+offsetNetRxErrors, *stats.Interfaces[0].RxErrors, label+".Net.TxErrors")
447 assert.EqualValues(t, seed+offsetNetTxBytes, *stats.Interfaces[0].TxBytes, label+".Net.TxErrors")
448 assert.EqualValues(t, seed+offsetNetTxErrors, *stats.Interfaces[0].TxErrors, label+".Net.TxErrors")
449
450 assert.EqualValues(t, "cbr0", stats.Interfaces[1].Name, "cbr0 interface name is not cbr0")
451 assert.EqualValues(t, 100, *stats.Interfaces[1].RxBytes, label+".Net.TxErrors")
452 assert.EqualValues(t, 100, *stats.Interfaces[1].RxErrors, label+".Net.TxErrors")
453 assert.EqualValues(t, 100, *stats.Interfaces[1].TxBytes, label+".Net.TxErrors")
454 assert.EqualValues(t, 100, *stats.Interfaces[1].TxErrors, label+".Net.TxErrors")
455
456 }
457
458 func checkCPUStats(t *testing.T, label string, seed int, stats *statsapi.CPUStats) {
459 require.NotNil(t, stats.Time, label+".CPU.Time")
460 require.NotNil(t, stats.UsageNanoCores, label+".CPU.UsageNanoCores")
461 require.NotNil(t, stats.UsageNanoCores, label+".CPU.UsageCoreSeconds")
462 assert.EqualValues(t, testTime(timestamp, seed).Unix(), stats.Time.Time.Unix(), label+".CPU.Time")
463 assert.EqualValues(t, seed+offsetCPUUsageCores, *stats.UsageNanoCores, label+".CPU.UsageCores")
464 assert.EqualValues(t, seed+offsetCPUUsageCoreSeconds, *stats.UsageCoreNanoSeconds, label+".CPU.UsageCoreSeconds")
465 }
466
467 func checkMemoryStats(t *testing.T, label string, seed int, info cadvisorapiv2.ContainerInfo, stats *statsapi.MemoryStats) {
468 assert.EqualValues(t, testTime(timestamp, seed).Unix(), stats.Time.Time.Unix(), label+".Mem.Time")
469 assert.EqualValues(t, seed+offsetMemUsageBytes, *stats.UsageBytes, label+".Mem.UsageBytes")
470 assert.EqualValues(t, seed+offsetMemWorkingSetBytes, *stats.WorkingSetBytes, label+".Mem.WorkingSetBytes")
471 assert.EqualValues(t, seed+offsetMemRSSBytes, *stats.RSSBytes, label+".Mem.RSSBytes")
472 assert.EqualValues(t, seed+offsetMemPageFaults, *stats.PageFaults, label+".Mem.PageFaults")
473 assert.EqualValues(t, seed+offsetMemMajorPageFaults, *stats.MajorPageFaults, label+".Mem.MajorPageFaults")
474 if !info.Spec.HasMemory || isMemoryUnlimited(info.Spec.Memory.Limit) {
475 assert.Nil(t, stats.AvailableBytes, label+".Mem.AvailableBytes")
476 } else {
477 expected := info.Spec.Memory.Limit - *stats.WorkingSetBytes
478 assert.EqualValues(t, expected, *stats.AvailableBytes, label+".Mem.AvailableBytes")
479 }
480 }
481
482 func checkSwapStats(t *testing.T, label string, seed int, info cadvisorapiv2.ContainerInfo, stats *statsapi.SwapStats) {
483 label += ".Swap"
484
485 assert.EqualValues(t, testTime(timestamp, seed).Unix(), stats.Time.Time.Unix(), label+".Time")
486 assert.EqualValues(t, seed+offsetMemSwapUsageBytes, *stats.SwapUsageBytes, label+".SwapUsageBytes")
487
488 if !info.Spec.HasMemory || isMemoryUnlimited(info.Spec.Memory.SwapLimit) {
489 assert.Nil(t, stats.SwapAvailableBytes, label+".SwapAvailableBytes")
490 } else {
491 expected := info.Spec.Memory.Limit - *stats.SwapUsageBytes
492 assert.EqualValues(t, expected, *stats.SwapAvailableBytes, label+".AvailableBytes")
493 }
494 }
495
496 func checkFsStats(t *testing.T, label string, seed int, stats *statsapi.FsStats) {
497 assert.EqualValues(t, seed+offsetFsCapacity, *stats.CapacityBytes, label+".CapacityBytes")
498 assert.EqualValues(t, seed+offsetFsAvailable, *stats.AvailableBytes, label+".AvailableBytes")
499 assert.EqualValues(t, seed+offsetFsInodes, *stats.Inodes, label+".Inodes")
500 assert.EqualValues(t, seed+offsetFsInodesFree, *stats.InodesFree, label+".InodesFree")
501 }
502
503 func checkEphemeralStats(t *testing.T, label string, containerSeeds []int, volumeSeeds []int, containerLogStats []*volume.Metrics, stats *statsapi.FsStats) {
504 var usedBytes, inodeUsage int
505 for _, cseed := range containerSeeds {
506 usedBytes += cseed + offsetFsBaseUsageBytes
507 inodeUsage += cseed + offsetFsInodeUsage
508
509
510
511
512 if containerLogStats == nil {
513 usedBytes += offsetFsTotalUsageBytes - offsetFsBaseUsageBytes
514 }
515 }
516 for _, vseed := range volumeSeeds {
517 usedBytes += vseed + offsetFsUsage
518 inodeUsage += vseed + offsetFsInodeUsage
519 }
520 for _, logStats := range containerLogStats {
521 usedBytes += int(logStats.Used.Value())
522 inodeUsage += int(logStats.InodesUsed.Value())
523 }
524 assert.EqualValues(t, usedBytes, int(*stats.UsedBytes), label+".UsedBytes")
525 assert.EqualValues(t, inodeUsage, int(*stats.InodesUsed), label+".InodesUsed")
526 }
527
528 type fakeResourceAnalyzer struct {
529 podVolumeStats serverstats.PodVolumeStats
530 }
531
532 func (o *fakeResourceAnalyzer) Start() {}
533 func (o *fakeResourceAnalyzer) Get(context.Context, bool) (*statsapi.Summary, error) { return nil, nil }
534 func (o *fakeResourceAnalyzer) GetCPUAndMemoryStats(context.Context) (*statsapi.Summary, error) {
535 return nil, nil
536 }
537 func (o *fakeResourceAnalyzer) GetPodVolumeStats(uid types.UID) (serverstats.PodVolumeStats, bool) {
538 return o.podVolumeStats, true
539 }
540
541 type fakeContainerStatsProvider struct {
542 device string
543 imageFs *statsapi.FsStats
544 containerFs *statsapi.FsStats
545 }
546
547 func (p fakeContainerStatsProvider) ListPodStats(context.Context) ([]statsapi.PodStats, error) {
548 return nil, fmt.Errorf("not implemented")
549 }
550
551 func (p fakeContainerStatsProvider) ListPodStatsAndUpdateCPUNanoCoreUsage(context.Context) ([]statsapi.PodStats, error) {
552 return nil, fmt.Errorf("not implemented")
553 }
554
555 func (p fakeContainerStatsProvider) ListPodCPUAndMemoryStats(context.Context) ([]statsapi.PodStats, error) {
556 return nil, fmt.Errorf("not implemented")
557 }
558
559 func (p fakeContainerStatsProvider) ImageFsStats(context.Context) (*statsapi.FsStats, *statsapi.FsStats, error) {
560 return p.imageFs, p.containerFs, nil
561 }
562
563 func (p fakeContainerStatsProvider) ImageFsDevice(context.Context) (string, error) {
564 return p.device, nil
565 }
566
View as plain text