k8s.io/kubernetes@v1.29.3/pkg/kubelet/stats/cri_stats_provider_windows_test.go (about) 1 /* 2 Copyright 2021 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package stats 18 19 import ( 20 "reflect" 21 "testing" 22 "time" 23 24 "github.com/Microsoft/hcsshim" 25 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1" 27 testingclock "k8s.io/utils/clock/testing" 28 ) 29 30 type fakeNetworkStatsProvider struct { 31 containers []containerStats 32 } 33 34 type containerStats struct { 35 container hcsshim.ContainerProperties 36 hcsStats []hcsshim.NetworkStats 37 } 38 39 func (s fakeNetworkStatsProvider) GetHNSEndpointStats(endpointName string) (*hcsshim.HNSEndpointStats, error) { 40 eps := hcsshim.HNSEndpointStats{} 41 for _, c := range s.containers { 42 for _, stat := range c.hcsStats { 43 if endpointName == stat.InstanceId { 44 eps = hcsshim.HNSEndpointStats{ 45 EndpointID: stat.EndpointId, 46 BytesSent: stat.BytesSent, 47 BytesReceived: stat.BytesReceived, 48 PacketsReceived: stat.PacketsReceived, 49 PacketsSent: stat.PacketsSent, 50 } 51 } 52 } 53 } 54 55 return &eps, nil 56 } 57 58 func (s fakeNetworkStatsProvider) HNSListEndpointRequest() ([]hcsshim.HNSEndpoint, error) { 59 uniqueEndpoints := map[string]*hcsshim.HNSEndpoint{} 60 61 for _, c := range s.containers { 62 for _, stat := range c.hcsStats { 63 e, found := uniqueEndpoints[stat.EndpointId] 64 if found { 65 // add the container 66 e.SharedContainers = append(e.SharedContainers, c.container.ID) 67 continue 68 } 69 70 uniqueEndpoints[stat.EndpointId] = &hcsshim.HNSEndpoint{ 71 Name: stat.EndpointId, 72 Id: stat.EndpointId, 73 SharedContainers: []string{c.container.ID}, 74 } 75 } 76 } 77 78 eps := []hcsshim.HNSEndpoint{} 79 for _, ep := range uniqueEndpoints { 80 eps = append(eps, *ep) 81 } 82 83 return eps, nil 84 } 85 86 func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) { 87 fakeClock := testingclock.NewFakeClock(time.Time{}) 88 tests := []struct { 89 name string 90 fields fakeNetworkStatsProvider 91 want map[string]*statsapi.NetworkStats 92 wantErr bool 93 skipped bool 94 }{ 95 { 96 name: "basic example", 97 fields: fakeNetworkStatsProvider{ 98 containers: []containerStats{ 99 { 100 container: hcsshim.ContainerProperties{ 101 ID: "c1", 102 }, hcsStats: []hcsshim.NetworkStats{ 103 { 104 BytesReceived: 1, 105 BytesSent: 10, 106 EndpointId: "test", 107 InstanceId: "test", 108 }, 109 }, 110 }, 111 { 112 container: hcsshim.ContainerProperties{ 113 ID: "c2", 114 }, hcsStats: []hcsshim.NetworkStats{ 115 { 116 BytesReceived: 2, 117 BytesSent: 20, 118 EndpointId: "test2", 119 InstanceId: "test2", 120 }, 121 }, 122 }, 123 }, 124 }, 125 want: map[string]*statsapi.NetworkStats{ 126 "c1": { 127 Time: v1.NewTime(fakeClock.Now()), 128 InterfaceStats: statsapi.InterfaceStats{ 129 Name: "test", 130 RxBytes: toP(1), 131 TxBytes: toP(10), 132 }, 133 Interfaces: []statsapi.InterfaceStats{ 134 { 135 Name: "test", 136 RxBytes: toP(1), 137 138 TxBytes: toP(10), 139 }, 140 }, 141 }, 142 "c2": { 143 Time: v1.Time{}, 144 InterfaceStats: statsapi.InterfaceStats{ 145 Name: "test2", 146 RxBytes: toP(2), 147 TxBytes: toP(20), 148 }, 149 Interfaces: []statsapi.InterfaceStats{ 150 { 151 Name: "test2", 152 RxBytes: toP(2), 153 TxBytes: toP(20), 154 }, 155 }, 156 }, 157 }, 158 wantErr: false, 159 }, 160 { 161 name: "multiple containers same endpoint", 162 fields: fakeNetworkStatsProvider{ 163 containers: []containerStats{ 164 { 165 container: hcsshim.ContainerProperties{ 166 ID: "c1", 167 }, hcsStats: []hcsshim.NetworkStats{ 168 { 169 BytesReceived: 1, 170 BytesSent: 10, 171 EndpointId: "test", 172 InstanceId: "test", 173 }, 174 }, 175 }, 176 { 177 container: hcsshim.ContainerProperties{ 178 ID: "c2", 179 }, hcsStats: []hcsshim.NetworkStats{ 180 { 181 BytesReceived: 2, 182 BytesSent: 20, 183 EndpointId: "test2", 184 InstanceId: "test2", 185 }, 186 }, 187 }, 188 { 189 container: hcsshim.ContainerProperties{ 190 ID: "c3", 191 }, hcsStats: []hcsshim.NetworkStats{ 192 { 193 BytesReceived: 3, 194 BytesSent: 30, 195 EndpointId: "test2", 196 InstanceId: "test3", 197 }, 198 }, 199 }, 200 }, 201 }, 202 want: map[string]*statsapi.NetworkStats{ 203 "c1": { 204 Time: v1.NewTime(fakeClock.Now()), 205 InterfaceStats: statsapi.InterfaceStats{ 206 Name: "test", 207 RxBytes: toP(1), 208 TxBytes: toP(10), 209 }, 210 Interfaces: []statsapi.InterfaceStats{ 211 { 212 Name: "test", 213 RxBytes: toP(1), 214 215 TxBytes: toP(10), 216 }, 217 }, 218 }, 219 "c2": { 220 Time: v1.Time{}, 221 InterfaceStats: statsapi.InterfaceStats{ 222 Name: "test2", 223 RxBytes: toP(2), 224 TxBytes: toP(20), 225 }, 226 Interfaces: []statsapi.InterfaceStats{ 227 { 228 Name: "test2", 229 RxBytes: toP(2), 230 TxBytes: toP(20), 231 }, 232 }, 233 }, 234 "c3": { 235 Time: v1.Time{}, 236 InterfaceStats: statsapi.InterfaceStats{ 237 Name: "test2", 238 RxBytes: toP(2), 239 TxBytes: toP(20), 240 }, 241 Interfaces: []statsapi.InterfaceStats{ 242 { 243 Name: "test2", 244 RxBytes: toP(2), 245 TxBytes: toP(20), 246 }, 247 }, 248 }, 249 }, 250 wantErr: false, 251 }, 252 { 253 name: "multiple stats instances of same interface only picks up first", 254 fields: fakeNetworkStatsProvider{ 255 containers: []containerStats{ 256 { 257 container: hcsshim.ContainerProperties{ 258 ID: "c1", 259 }, hcsStats: []hcsshim.NetworkStats{ 260 { 261 BytesReceived: 1, 262 BytesSent: 10, 263 EndpointId: "test", 264 InstanceId: "test", 265 }, 266 { 267 BytesReceived: 3, 268 BytesSent: 30, 269 EndpointId: "test", 270 InstanceId: "test3", 271 }, 272 }, 273 }, 274 { 275 container: hcsshim.ContainerProperties{ 276 ID: "c2", 277 }, hcsStats: []hcsshim.NetworkStats{ 278 { 279 BytesReceived: 2, 280 BytesSent: 20, 281 EndpointId: "test2", 282 InstanceId: "test2", 283 }, 284 }, 285 }, 286 }, 287 }, 288 want: map[string]*statsapi.NetworkStats{ 289 "c1": { 290 Time: v1.NewTime(fakeClock.Now()), 291 InterfaceStats: statsapi.InterfaceStats{ 292 Name: "test", 293 RxBytes: toP(1), 294 TxBytes: toP(10), 295 }, 296 Interfaces: []statsapi.InterfaceStats{ 297 { 298 Name: "test", 299 RxBytes: toP(1), 300 301 TxBytes: toP(10), 302 }, 303 }, 304 }, 305 "c2": { 306 Time: v1.Time{}, 307 InterfaceStats: statsapi.InterfaceStats{ 308 Name: "test2", 309 RxBytes: toP(2), 310 TxBytes: toP(20), 311 }, 312 Interfaces: []statsapi.InterfaceStats{ 313 { 314 Name: "test2", 315 RxBytes: toP(2), 316 TxBytes: toP(20), 317 }, 318 }, 319 }, 320 }, 321 wantErr: false, 322 }, 323 { 324 name: "multiple endpoints per container", 325 fields: fakeNetworkStatsProvider{ 326 containers: []containerStats{ 327 { 328 container: hcsshim.ContainerProperties{ 329 ID: "c1", 330 }, hcsStats: []hcsshim.NetworkStats{ 331 { 332 BytesReceived: 1, 333 BytesSent: 10, 334 EndpointId: "test", 335 InstanceId: "test", 336 }, 337 { 338 BytesReceived: 3, 339 BytesSent: 30, 340 EndpointId: "test3", 341 InstanceId: "test3", 342 }, 343 }, 344 }, 345 { 346 container: hcsshim.ContainerProperties{ 347 ID: "c2", 348 }, hcsStats: []hcsshim.NetworkStats{ 349 { 350 BytesReceived: 2, 351 BytesSent: 20, 352 EndpointId: "test2", 353 InstanceId: "test2", 354 }, 355 }, 356 }, 357 }, 358 }, 359 want: map[string]*statsapi.NetworkStats{ 360 "c1": { 361 Time: v1.NewTime(fakeClock.Now()), 362 InterfaceStats: statsapi.InterfaceStats{ 363 Name: "test", 364 RxBytes: toP(1), 365 TxBytes: toP(10), 366 }, 367 Interfaces: []statsapi.InterfaceStats{ 368 { 369 Name: "test", 370 RxBytes: toP(1), 371 372 TxBytes: toP(10), 373 }, 374 { 375 Name: "test3", 376 RxBytes: toP(3), 377 378 TxBytes: toP(30), 379 }, 380 }, 381 }, 382 "c2": { 383 Time: v1.Time{}, 384 InterfaceStats: statsapi.InterfaceStats{ 385 Name: "test2", 386 RxBytes: toP(2), 387 TxBytes: toP(20), 388 }, 389 Interfaces: []statsapi.InterfaceStats{ 390 { 391 Name: "test2", 392 RxBytes: toP(2), 393 TxBytes: toP(20), 394 }, 395 }, 396 }, 397 }, 398 wantErr: false, 399 skipped: true, 400 }, 401 } 402 for _, tt := range tests { 403 t.Run(tt.name, func(t *testing.T) { 404 // TODO: Remove skip once https://github.com/kubernetes/kubernetes/issues/116692 is fixed. 405 if tt.skipped { 406 t.Skip("Test temporarily skipped.") 407 } 408 p := &criStatsProvider{ 409 windowsNetworkStatsProvider: fakeNetworkStatsProvider{ 410 containers: tt.fields.containers, 411 }, 412 clock: fakeClock, 413 } 414 got, err := p.listContainerNetworkStats() 415 if (err != nil) != tt.wantErr { 416 t.Errorf("listContainerNetworkStats() error = %v, wantErr %v", err, tt.wantErr) 417 return 418 } 419 if !reflect.DeepEqual(got, tt.want) { 420 t.Errorf("listContainerNetworkStats() got = %v, want %v", got, tt.want) 421 } 422 }) 423 } 424 } 425 426 func toP(i uint64) *uint64 { 427 return &i 428 }