mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Get networks stats directly
This commit is contained in:
		@@ -38,6 +38,7 @@ import (
 | 
				
			|||||||
	"k8s.io/kubernetes/pkg/kubelet/cadvisor"
 | 
						"k8s.io/kubernetes/pkg/kubelet/cadvisor"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/kubelet/server/stats"
 | 
						"k8s.io/kubernetes/pkg/kubelet/server/stats"
 | 
				
			||||||
	kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
 | 
						kubetypes "k8s.io/kubernetes/pkg/kubelet/types"
 | 
				
			||||||
 | 
						"k8s.io/utils/clock"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
@@ -67,7 +68,11 @@ type criStatsProvider struct {
 | 
				
			|||||||
	imageService internalapi.ImageManagerService
 | 
						imageService internalapi.ImageManagerService
 | 
				
			||||||
	// hostStatsProvider is used to get the status of the host filesystem consumed by pods.
 | 
						// hostStatsProvider is used to get the status of the host filesystem consumed by pods.
 | 
				
			||||||
	hostStatsProvider HostStatsProvider
 | 
						hostStatsProvider HostStatsProvider
 | 
				
			||||||
	hcsshimInterface  interface{}
 | 
						//lint:ignore U1000 We can't import hcsshim due to Build constraints in hcsshim
 | 
				
			||||||
 | 
						// windowsNetworkStatsProvider is used by kubelet to gather networking stats on Windows
 | 
				
			||||||
 | 
						windowsNetworkStatsProvider interface{}
 | 
				
			||||||
 | 
						// clock is used report current time
 | 
				
			||||||
 | 
						clock clock.Clock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// cpuUsageCache caches the cpu usage for containers.
 | 
						// cpuUsageCache caches the cpu usage for containers.
 | 
				
			||||||
	cpuUsageCache                  map[string]*cpuUsageRecord
 | 
						cpuUsageCache                  map[string]*cpuUsageRecord
 | 
				
			||||||
@@ -96,6 +101,7 @@ func newCRIStatsProvider(
 | 
				
			|||||||
		cpuUsageCache:                  make(map[string]*cpuUsageRecord),
 | 
							cpuUsageCache:                  make(map[string]*cpuUsageRecord),
 | 
				
			||||||
		disableAcceleratorUsageMetrics: disableAcceleratorUsageMetrics,
 | 
							disableAcceleratorUsageMetrics: disableAcceleratorUsageMetrics,
 | 
				
			||||||
		podAndContainerStatsFromCRI:    podAndContainerStatsFromCRI,
 | 
							podAndContainerStatsFromCRI:    podAndContainerStatsFromCRI,
 | 
				
			||||||
 | 
							clock:                          clock.RealClock{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,135 +20,98 @@ limitations under the License.
 | 
				
			|||||||
package stats
 | 
					package stats
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/Microsoft/hcsshim"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
					 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
					 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
						"k8s.io/klog/v2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/Microsoft/hcsshim"
 | 
				
			||||||
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
 | 
						statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type hcsShimInterface interface {
 | 
					// windowsNetworkStatsProvider creates an interface that allows for testing the logic without needing to create a container
 | 
				
			||||||
	GetContainers(q hcsshim.ComputeSystemQuery) ([]hcsshim.ContainerProperties, error)
 | 
					type windowsNetworkStatsProvider interface {
 | 
				
			||||||
	GetHNSEndpointByID(endpointID string) (*hcsshim.HNSEndpoint, error)
 | 
						HNSListEndpointRequest() ([]hcsshim.HNSEndpoint, error)
 | 
				
			||||||
	OpenContainer(id string) (hcsshim.Container, error)
 | 
						GetHNSEndpointStats(endpointName string) (*hcsshim.HNSEndpointStats, error)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type windowshim struct{}
 | 
					// networkStats exposes the required functionality for hcsshim in this scenario
 | 
				
			||||||
 | 
					type networkStats struct{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s windowshim) GetContainers(q hcsshim.ComputeSystemQuery) ([]hcsshim.ContainerProperties, error) {
 | 
					func (s networkStats) HNSListEndpointRequest() ([]hcsshim.HNSEndpoint, error) {
 | 
				
			||||||
	return hcsshim.GetContainers(q)
 | 
						return hcsshim.HNSListEndpointRequest()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s windowshim) GetHNSEndpointByID(endpointID string) (*hcsshim.HNSEndpoint, error) {
 | 
					func (s networkStats) GetHNSEndpointStats(endpointName string) (*hcsshim.HNSEndpointStats, error) {
 | 
				
			||||||
	return hcsshim.GetHNSEndpointByID(endpointID)
 | 
						return hcsshim.GetHNSEndpointStats(endpointName)
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s windowshim) OpenContainer(id string) (hcsshim.Container, error) {
 | 
					 | 
				
			||||||
	return hcsshim.OpenContainer(id)
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// listContainerNetworkStats returns the network stats of all the running containers.
 | 
					// listContainerNetworkStats returns the network stats of all the running containers.
 | 
				
			||||||
func (p *criStatsProvider) listContainerNetworkStats() (map[string]*statsapi.NetworkStats, error) {
 | 
					func (p *criStatsProvider) listContainerNetworkStats() (map[string]*statsapi.NetworkStats, error) {
 | 
				
			||||||
	shim := newHcsShim(p)
 | 
						networkStatsProvider := newNetworkStatsProvider(p)
 | 
				
			||||||
	containers, err := shim.GetContainers(hcsshim.ComputeSystemQuery{
 | 
					
 | 
				
			||||||
		Types: []string{"Container"},
 | 
						endpoints, err := networkStatsProvider.HNSListEndpointRequest()
 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							klog.ErrorS(err, "Failed to fetch current HNS endpoints")
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stats := make(map[string]*statsapi.NetworkStats)
 | 
						networkStats := make(map[string]*statsapi.NetworkStats)
 | 
				
			||||||
	for _, c := range containers {
 | 
						for _, endpoint := range endpoints {
 | 
				
			||||||
		cstats, err := fetchContainerStats(shim, c)
 | 
							endpointStats, err := networkStatsProvider.GetHNSEndpointStats(endpoint.Id)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			klog.V(4).InfoS("Failed to fetch statistics for container, continue to get stats for other containers", "containerID", c.ID, "err", err)
 | 
								klog.V(2).InfoS("Failed to fetch statistics for endpoint, continue to get stats for other endpoints", "endpointId", endpoint.Id, "containers", endpoint.SharedContainers)
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if len(cstats.Network) > 0 {
 | 
					
 | 
				
			||||||
			stats[c.ID] = hcsStatsToNetworkStats(shim, cstats.Timestamp, cstats.Network)
 | 
							// only add the interface for each container if not already in the list
 | 
				
			||||||
 | 
							for _, cId := range endpoint.SharedContainers {
 | 
				
			||||||
 | 
								networkStat, found := networkStats[cId]
 | 
				
			||||||
 | 
								if found && networkStat.Name != endpoint.Name {
 | 
				
			||||||
 | 
									iStat := hcsStatToInterfaceStat(endpointStats, endpoint.Name)
 | 
				
			||||||
 | 
									networkStat.Interfaces = append(networkStat.Interfaces, iStat)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								networkStats[cId] = hcsStatsToNetworkStats(p.clock.Now(), endpointStats, endpoint.Name)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return stats, nil
 | 
						return networkStats, nil
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newHcsShim(p *criStatsProvider) hcsShimInterface {
 | 
					 | 
				
			||||||
	var shim hcsShimInterface
 | 
					 | 
				
			||||||
	if p.hcsshimInterface == nil {
 | 
					 | 
				
			||||||
		shim = windowshim{}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		shim = p.hcsshimInterface.(hcsShimInterface)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return shim
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func fetchContainerStats(hcsshimInterface hcsShimInterface, c hcsshim.ContainerProperties) (stats hcsshim.Statistics, err error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		container hcsshim.Container
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	container, err = hcsshimInterface.OpenContainer(c.ID)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer func() {
 | 
					 | 
				
			||||||
		if closeErr := container.Close(); closeErr != nil {
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				err = fmt.Errorf("failed to close container after error %v; close error: %v", err, closeErr)
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				err = closeErr
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return container.Statistics()
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// hcsStatsToNetworkStats converts hcsshim.Statistics.Network to statsapi.NetworkStats
 | 
					// hcsStatsToNetworkStats converts hcsshim.Statistics.Network to statsapi.NetworkStats
 | 
				
			||||||
func hcsStatsToNetworkStats(hcsshimInterface hcsShimInterface, timestamp time.Time, hcsStats []hcsshim.NetworkStats) *statsapi.NetworkStats {
 | 
					func hcsStatsToNetworkStats(timestamp time.Time, hcsStats *hcsshim.HNSEndpointStats, endpointName string) *statsapi.NetworkStats {
 | 
				
			||||||
	result := &statsapi.NetworkStats{
 | 
						result := &statsapi.NetworkStats{
 | 
				
			||||||
		Time:       metav1.NewTime(timestamp),
 | 
							Time:       metav1.NewTime(timestamp),
 | 
				
			||||||
		Interfaces: make([]statsapi.InterfaceStats, 0),
 | 
							Interfaces: make([]statsapi.InterfaceStats, 0),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	adapters := sets.NewString()
 | 
						iStat := hcsStatToInterfaceStat(hcsStats, endpointName)
 | 
				
			||||||
	for _, stat := range hcsStats {
 | 
					 | 
				
			||||||
		iStat, err := hcsStatsToInterfaceStats(hcsshimInterface, stat)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			klog.InfoS("Failed to get HNS endpoint, continue to get stats for other endpoints", "endpointID", stat.EndpointId, "err", err)
 | 
					 | 
				
			||||||
			continue
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Only count each adapter once.
 | 
						// TODO: add support of multiple interfaces for getting default interface.
 | 
				
			||||||
		if adapters.Has(iStat.Name) {
 | 
						result.Interfaces = append(result.Interfaces, iStat)
 | 
				
			||||||
			continue
 | 
						result.InterfaceStats = iStat
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		result.Interfaces = append(result.Interfaces, *iStat)
 | 
					 | 
				
			||||||
		adapters.Insert(iStat.Name)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// TODO(feiskyer): add support of multiple interfaces for getting default interface.
 | 
					 | 
				
			||||||
	if len(result.Interfaces) > 0 {
 | 
					 | 
				
			||||||
		result.InterfaceStats = result.Interfaces[0]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return result
 | 
						return result
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// hcsStatsToInterfaceStats converts hcsshim.NetworkStats to statsapi.InterfaceStats.
 | 
					func hcsStatToInterfaceStat(hcsStats *hcsshim.HNSEndpointStats, endpointName string) statsapi.InterfaceStats {
 | 
				
			||||||
func hcsStatsToInterfaceStats(hcsshimInterface hcsShimInterface, stat hcsshim.NetworkStats) (*statsapi.InterfaceStats, error) {
 | 
						iStat := statsapi.InterfaceStats{
 | 
				
			||||||
	endpoint, err := hcsshimInterface.GetHNSEndpointByID(stat.EndpointId)
 | 
							Name:    endpointName,
 | 
				
			||||||
	if err != nil {
 | 
							RxBytes: &hcsStats.BytesReceived,
 | 
				
			||||||
		return nil, err
 | 
							TxBytes: &hcsStats.BytesSent,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return iStat
 | 
				
			||||||
	return &statsapi.InterfaceStats{
 | 
					}
 | 
				
			||||||
		Name:    endpoint.Name,
 | 
					
 | 
				
			||||||
		RxBytes: &stat.BytesReceived,
 | 
					// newNetworkStatsProvider uses the real windows hcsshim if not provided otherwise if the interface is provided
 | 
				
			||||||
		TxBytes: &stat.BytesSent,
 | 
					// by the cristatsprovider in testing scenarios it uses that one
 | 
				
			||||||
	}, nil
 | 
					func newNetworkStatsProvider(p *criStatsProvider) windowsNetworkStatsProvider {
 | 
				
			||||||
 | 
						var statsProvider windowsNetworkStatsProvider
 | 
				
			||||||
 | 
						if p.windowsNetworkStatsProvider == nil {
 | 
				
			||||||
 | 
							statsProvider = networkStats{}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							statsProvider = p.windowsNetworkStatsProvider.(windowsNetworkStatsProvider)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return statsProvider
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,19 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2021 The Kubernetes Authors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package stats
 | 
					package stats
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
@@ -6,107 +22,12 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/Microsoft/hcsshim"
 | 
						"github.com/Microsoft/hcsshim"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
 | 
						statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
 | 
				
			||||||
 | 
						testingclock "k8s.io/utils/clock/testing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type fakeNetworkStatsProvider struct {
 | 
				
			||||||
 | 
					 | 
				
			||||||
type fakeConatiner struct {
 | 
					 | 
				
			||||||
	stat hcsshim.Statistics
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Start() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Shutdown() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Terminate() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Wait() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) WaitTimeout(duration time.Duration) error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Pause() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Resume() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) HasPendingUpdates() (bool, error) {
 | 
					 | 
				
			||||||
	return false, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Statistics() (hcsshim.Statistics, error) {
 | 
					 | 
				
			||||||
	return f.stat, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) ProcessList() ([]hcsshim.ProcessListItem, error) {
 | 
					 | 
				
			||||||
	return []hcsshim.ProcessListItem{}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) MappedVirtualDisks() (map[int]hcsshim.MappedVirtualDiskController, error) {
 | 
					 | 
				
			||||||
	return map[int]hcsshim.MappedVirtualDiskController{}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) CreateProcess(c *hcsshim.ProcessConfig) (hcsshim.Process, error) {
 | 
					 | 
				
			||||||
	return nil, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) OpenProcess(pid int) (hcsshim.Process, error) {
 | 
					 | 
				
			||||||
	return nil, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Close() error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (f fakeConatiner) Modify(config *hcsshim.ResourceModificationRequestResponse) error {
 | 
					 | 
				
			||||||
	return nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s fakehcsshim) GetContainers(q hcsshim.ComputeSystemQuery) ([]hcsshim.ContainerProperties, error) {
 | 
					 | 
				
			||||||
	cp := []hcsshim.ContainerProperties{}
 | 
					 | 
				
			||||||
	for _, c := range s.containers  {
 | 
					 | 
				
			||||||
		cp = append(cp, c.container)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return cp, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s fakehcsshim) GetHNSEndpointByID(endpointID string) (*hcsshim.HNSEndpoint, error) {
 | 
					 | 
				
			||||||
	e := hcsshim.HNSEndpoint{
 | 
					 | 
				
			||||||
		Name: endpointID,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &e, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (s fakehcsshim) OpenContainer(id string) (hcsshim.Container, error) {
 | 
					 | 
				
			||||||
	fc := fakeConatiner{}
 | 
					 | 
				
			||||||
	for _, c := range s.containers {
 | 
					 | 
				
			||||||
		if c.container.ID == id {
 | 
					 | 
				
			||||||
			for _, s := range c.hcsStats{
 | 
					 | 
				
			||||||
				fc.stat.Network = append(fc.stat.Network, s)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return fc, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type fakehcsshim struct {
 | 
					 | 
				
			||||||
	containers []containerStats
 | 
						containers []containerStats
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,17 +36,64 @@ type containerStats struct {
 | 
				
			|||||||
	hcsStats  []hcsshim.NetworkStats
 | 
						hcsStats  []hcsshim.NetworkStats
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s fakeNetworkStatsProvider) GetHNSEndpointStats(endpointName string) (*hcsshim.HNSEndpointStats, error) {
 | 
				
			||||||
 | 
						eps := hcsshim.HNSEndpointStats{}
 | 
				
			||||||
 | 
						for _, c := range s.containers {
 | 
				
			||||||
 | 
							for _, stat := range c.hcsStats {
 | 
				
			||||||
 | 
								if endpointName == stat.InstanceId {
 | 
				
			||||||
 | 
									eps = hcsshim.HNSEndpointStats{
 | 
				
			||||||
 | 
										EndpointID:      stat.EndpointId,
 | 
				
			||||||
 | 
										BytesSent:       stat.BytesSent,
 | 
				
			||||||
 | 
										BytesReceived:   stat.BytesReceived,
 | 
				
			||||||
 | 
										PacketsReceived: stat.PacketsReceived,
 | 
				
			||||||
 | 
										PacketsSent:     stat.PacketsSent,
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &eps, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s fakeNetworkStatsProvider) HNSListEndpointRequest() ([]hcsshim.HNSEndpoint, error) {
 | 
				
			||||||
 | 
						uniqueEndpoints := map[string]*hcsshim.HNSEndpoint{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, c := range s.containers {
 | 
				
			||||||
 | 
							for _, stat := range c.hcsStats {
 | 
				
			||||||
 | 
								e, found := uniqueEndpoints[stat.EndpointId]
 | 
				
			||||||
 | 
								if found {
 | 
				
			||||||
 | 
									// add the container
 | 
				
			||||||
 | 
									e.SharedContainers = append(e.SharedContainers, c.container.ID)
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								uniqueEndpoints[stat.EndpointId] = &hcsshim.HNSEndpoint{
 | 
				
			||||||
 | 
									Name:             stat.EndpointId,
 | 
				
			||||||
 | 
									Id:               stat.EndpointId,
 | 
				
			||||||
 | 
									SharedContainers: []string{c.container.ID},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						eps := []hcsshim.HNSEndpoint{}
 | 
				
			||||||
 | 
						for _, ep := range uniqueEndpoints {
 | 
				
			||||||
 | 
							eps = append(eps, *ep)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return eps, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
					func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			||||||
 | 
						fakeClock := testingclock.NewFakeClock(time.Time{})
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		name    string
 | 
							name    string
 | 
				
			||||||
		fields  fakehcsshim
 | 
							fields  fakeNetworkStatsProvider
 | 
				
			||||||
		want    map[string]*statsapi.NetworkStats
 | 
							want    map[string]*statsapi.NetworkStats
 | 
				
			||||||
		wantErr bool
 | 
							wantErr bool
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "basic example",
 | 
								name: "basic example",
 | 
				
			||||||
			fields: fakehcsshim{
 | 
								fields: fakeNetworkStatsProvider{
 | 
				
			||||||
				containers: []containerStats{
 | 
									containers: []containerStats{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						container: hcsshim.ContainerProperties{
 | 
											container: hcsshim.ContainerProperties{
 | 
				
			||||||
@@ -154,8 +122,8 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			want: map[string]*statsapi.NetworkStats{
 | 
								want: map[string]*statsapi.NetworkStats{
 | 
				
			||||||
				"c1": &statsapi.NetworkStats{
 | 
									"c1": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.NewTime(fakeClock.Now()),
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test",
 | 
											Name:    "test",
 | 
				
			||||||
						RxBytes: toP(1),
 | 
											RxBytes: toP(1),
 | 
				
			||||||
@@ -170,7 +138,7 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				"c2": &statsapi.NetworkStats{
 | 
									"c2": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.Time{},
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test2",
 | 
											Name:    "test2",
 | 
				
			||||||
@@ -190,7 +158,7 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "multiple containers same endpoint",
 | 
								name: "multiple containers same endpoint",
 | 
				
			||||||
			fields: fakehcsshim{
 | 
								fields: fakeNetworkStatsProvider{
 | 
				
			||||||
				containers: []containerStats{
 | 
									containers: []containerStats{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						container: hcsshim.ContainerProperties{
 | 
											container: hcsshim.ContainerProperties{
 | 
				
			||||||
@@ -231,8 +199,8 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			want: map[string]*statsapi.NetworkStats{
 | 
								want: map[string]*statsapi.NetworkStats{
 | 
				
			||||||
				"c1": &statsapi.NetworkStats{
 | 
									"c1": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.NewTime(fakeClock.Now()),
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test",
 | 
											Name:    "test",
 | 
				
			||||||
						RxBytes: toP(1),
 | 
											RxBytes: toP(1),
 | 
				
			||||||
@@ -247,7 +215,7 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				"c2": &statsapi.NetworkStats{
 | 
									"c2": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.Time{},
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test2",
 | 
											Name:    "test2",
 | 
				
			||||||
@@ -262,18 +230,18 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				"c3": &statsapi.NetworkStats{
 | 
									"c3": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.Time{},
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test2",
 | 
											Name:    "test2",
 | 
				
			||||||
						RxBytes: toP(3),
 | 
											RxBytes: toP(2),
 | 
				
			||||||
						TxBytes: toP(30),
 | 
											TxBytes: toP(20),
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
					Interfaces: []statsapi.InterfaceStats{
 | 
										Interfaces: []statsapi.InterfaceStats{
 | 
				
			||||||
						{
 | 
											{
 | 
				
			||||||
							Name:    "test2",
 | 
												Name:    "test2",
 | 
				
			||||||
							RxBytes: toP(3),
 | 
												RxBytes: toP(2),
 | 
				
			||||||
							TxBytes: toP(30),
 | 
												TxBytes: toP(20),
 | 
				
			||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
@@ -282,7 +250,7 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "multiple stats instances of same interface only picks up first",
 | 
								name: "multiple stats instances of same interface only picks up first",
 | 
				
			||||||
			fields: fakehcsshim{
 | 
								fields: fakeNetworkStatsProvider{
 | 
				
			||||||
				containers: []containerStats{
 | 
									containers: []containerStats{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						container: hcsshim.ContainerProperties{
 | 
											container: hcsshim.ContainerProperties{
 | 
				
			||||||
@@ -317,8 +285,8 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			want: map[string]*statsapi.NetworkStats{
 | 
								want: map[string]*statsapi.NetworkStats{
 | 
				
			||||||
				"c1": &statsapi.NetworkStats{
 | 
									"c1": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.NewTime(fakeClock.Now()),
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test",
 | 
											Name:    "test",
 | 
				
			||||||
						RxBytes: toP(1),
 | 
											RxBytes: toP(1),
 | 
				
			||||||
@@ -333,7 +301,7 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				"c2": &statsapi.NetworkStats{
 | 
									"c2": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.Time{},
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test2",
 | 
											Name:    "test2",
 | 
				
			||||||
@@ -353,7 +321,7 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			name: "multiple endpoints per container",
 | 
								name: "multiple endpoints per container",
 | 
				
			||||||
			fields: fakehcsshim{
 | 
								fields: fakeNetworkStatsProvider{
 | 
				
			||||||
				containers: []containerStats{
 | 
									containers: []containerStats{
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						container: hcsshim.ContainerProperties{
 | 
											container: hcsshim.ContainerProperties{
 | 
				
			||||||
@@ -388,8 +356,8 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			want: map[string]*statsapi.NetworkStats{
 | 
								want: map[string]*statsapi.NetworkStats{
 | 
				
			||||||
				"c1": &statsapi.NetworkStats{
 | 
									"c1": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.NewTime(fakeClock.Now()),
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test",
 | 
											Name:    "test",
 | 
				
			||||||
						RxBytes: toP(1),
 | 
											RxBytes: toP(1),
 | 
				
			||||||
@@ -410,7 +378,7 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
						},
 | 
											},
 | 
				
			||||||
					},
 | 
										},
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
				"c2": &statsapi.NetworkStats{
 | 
									"c2": {
 | 
				
			||||||
					Time: v1.Time{},
 | 
										Time: v1.Time{},
 | 
				
			||||||
					InterfaceStats: statsapi.InterfaceStats{
 | 
										InterfaceStats: statsapi.InterfaceStats{
 | 
				
			||||||
						Name:    "test2",
 | 
											Name:    "test2",
 | 
				
			||||||
@@ -432,9 +400,10 @@ func Test_criStatsProvider_listContainerNetworkStats(t *testing.T) {
 | 
				
			|||||||
	for _, tt := range tests {
 | 
						for _, tt := range tests {
 | 
				
			||||||
		t.Run(tt.name, func(t *testing.T) {
 | 
							t.Run(tt.name, func(t *testing.T) {
 | 
				
			||||||
			p := &criStatsProvider{
 | 
								p := &criStatsProvider{
 | 
				
			||||||
				hcsshimInterface: fakehcsshim{
 | 
									windowsNetworkStatsProvider: fakeNetworkStatsProvider{
 | 
				
			||||||
					containers: tt.fields.containers,
 | 
										containers: tt.fields.containers,
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
 | 
									clock: fakeClock,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			got, err := p.listContainerNetworkStats()
 | 
								got, err := p.listContainerNetworkStats()
 | 
				
			||||||
			if (err != nil) != tt.wantErr {
 | 
								if (err != nil) != tt.wantErr {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user