github.com/kubewharf/katalyst-core@v0.5.3/pkg/agent/orm/manager_test.go (about)

     1  /*
     2  Copyright 2022 The Katalyst 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 orm
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  	"testing"
    25  	"time"
    26  
    27  	cadvisorapi "github.com/google/cadvisor/info/v1"
    28  	"github.com/stretchr/testify/assert"
    29  	"google.golang.org/grpc"
    30  	v1 "k8s.io/api/core/v1"
    31  	"k8s.io/apimachinery/pkg/api/resource"
    32  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	"k8s.io/apimachinery/pkg/runtime"
    34  	"k8s.io/apimachinery/pkg/util/uuid"
    35  	pluginapi "k8s.io/kubelet/pkg/apis/resourceplugin/v1alpha1"
    36  	"k8s.io/kubernetes/pkg/kubelet/checkpointmanager"
    37  
    38  	katalyst_base "github.com/kubewharf/katalyst-core/cmd/base"
    39  	"github.com/kubewharf/katalyst-core/cmd/katalyst-agent/app/options"
    40  	"github.com/kubewharf/katalyst-core/pkg/agent/orm/endpoint"
    41  	"github.com/kubewharf/katalyst-core/pkg/agent/orm/executor"
    42  	"github.com/kubewharf/katalyst-core/pkg/agent/orm/metamanager"
    43  	"github.com/kubewharf/katalyst-core/pkg/agent/orm/topology"
    44  	"github.com/kubewharf/katalyst-core/pkg/config"
    45  	"github.com/kubewharf/katalyst-core/pkg/config/generic"
    46  	"github.com/kubewharf/katalyst-core/pkg/metaserver"
    47  	"github.com/kubewharf/katalyst-core/pkg/metaserver/agent/pod"
    48  	"github.com/kubewharf/katalyst-core/pkg/metrics"
    49  	cgroupmgr "github.com/kubewharf/katalyst-core/pkg/util/cgroup/manager"
    50  )
    51  
    52  func TestProcess(t *testing.T) {
    53  	t.Parallel()
    54  
    55  	res1 := TestResource{
    56  		resourceName:     "domain1.com/resource1",
    57  		resourceQuantity: *resource.NewQuantity(int64(2), resource.DecimalSI),
    58  	}
    59  	res2 := TestResource{
    60  		resourceName:     "domain2.com/resource2",
    61  		resourceQuantity: *resource.NewQuantity(int64(2), resource.DecimalSI),
    62  	}
    63  
    64  	testResources := []TestResource{
    65  		res1,
    66  		res2,
    67  	}
    68  
    69  	pods := []*v1.Pod{
    70  		makePod("testPod", v1.ResourceList{
    71  			"domain1.com/resource1": *resource.NewQuantity(2, resource.DecimalSI),
    72  			"domain2.com/resource2": *resource.NewQuantity(2, resource.DecimalSI),
    73  		}),
    74  		makePod("skipPod", v1.ResourceList{
    75  			"domain1.com/resource1": *resource.NewQuantity(2, resource.DecimalSI),
    76  			"domain2.com/resource2": *resource.NewQuantity(2, resource.DecimalSI),
    77  		}),
    78  	}
    79  	pods[1].OwnerReferences = []metav1.OwnerReference{
    80  		{
    81  			Kind: "DaemonSet",
    82  		},
    83  	}
    84  
    85  	ckDir, err := ioutil.TempDir("", "checkpoint-Test")
    86  	assert.NoError(t, err)
    87  	defer func() { _ = os.RemoveAll(ckDir) }()
    88  
    89  	conf := generateTestConfiguration(ckDir)
    90  	metaServer, err := generateTestMetaServer(conf, pods)
    91  	assert.NoError(t, err)
    92  	metamanager := metamanager.NewManager(metrics.DummyMetrics{}, nil, metaServer)
    93  
    94  	checkpointManager, err := checkpointmanager.NewCheckpointManager("/tmp/process")
    95  	assert.NoError(t, err)
    96  
    97  	ctx, cancel := context.WithCancel(context.Background())
    98  	defer cancel()
    99  
   100  	m := &ManagerImpl{
   101  		ctx:               ctx,
   102  		endpoints:         map[string]endpoint.EndpointInfo{},
   103  		socketdir:         "/tmp/process",
   104  		metaManager:       metamanager,
   105  		resourceNamesMap:  map[string]string{},
   106  		podResources:      newPodResourcesChk(),
   107  		resourceExecutor:  executor.NewExecutor(&cgroupmgr.FakeCgroupManager{}),
   108  		checkpointManager: checkpointManager,
   109  		podAddChan:        make(chan string, 1),
   110  		podDeleteChan:     make(chan string, 1),
   111  		qosConfig:         generic.NewQoSConfiguration(),
   112  	}
   113  	defer func() { _ = os.Remove("/tmp/process/kubelet_qrm_checkpoint") }()
   114  	topologyManager, _ := topology.NewManager([]cadvisorapi.Node{
   115  		{
   116  			Id: 0,
   117  		},
   118  	}, "restricted", nil)
   119  	topologyManager.AddHintProvider(m)
   120  	m.topologyManager = topologyManager
   121  	err = registerEndpointByRes(m, testResources)
   122  	assert.NoError(t, err)
   123  
   124  	go m.process()
   125  
   126  	for _, pod := range pods {
   127  		m.onPodAdd(string(pod.UID))
   128  	}
   129  
   130  	time.Sleep(1 * time.Second)
   131  	containerResources := m.podResources.podResources(string(pods[0].UID))
   132  	assert.NotNil(t, containerResources)
   133  	assert.Equal(t, len(containerResources), 1)
   134  
   135  	for _, containerResource := range containerResources {
   136  		assert.Equal(t, len(containerResource), 2)
   137  		allocationInfo, ok := containerResource["domain1.com/resource1"]
   138  		assert.True(t, ok)
   139  		assert.Equal(t, allocationInfo.OciPropertyName, "CpusetCpus")
   140  
   141  		allocationInfo, ok = containerResource["domain2.com/resource2"]
   142  		assert.True(t, ok)
   143  		assert.Equal(t, allocationInfo.OciPropertyName, "CpusetMems")
   144  	}
   145  
   146  	containerResources = m.podResources.podResources(string(pods[1].UID))
   147  	assert.Nil(t, containerResources)
   148  
   149  	// remove pod
   150  	for _, pod := range pods {
   151  		m.onPodDelete(string(pod.UID))
   152  	}
   153  	time.Sleep(500 * time.Millisecond)
   154  	assert.Equal(t, len(m.podResources.allAllocatedResourceNames()), 0)
   155  	assert.Equal(t, len(m.podResources.pods()), 0)
   156  }
   157  
   158  func TestReconcile(t *testing.T) {
   159  	t.Parallel()
   160  
   161  	pods := []*v1.Pod{
   162  		makePod("testPod1", v1.ResourceList{
   163  			"cpu":    *resource.NewQuantity(2, resource.DecimalSI),
   164  			"memory": *resource.NewQuantity(2, resource.DecimalSI),
   165  		}),
   166  		makePod("testPod2", v1.ResourceList{
   167  			"cpu":    *resource.NewQuantity(2, resource.DecimalSI),
   168  			"memory": *resource.NewQuantity(2, resource.DecimalSI),
   169  		}),
   170  	}
   171  
   172  	ckDir, err := ioutil.TempDir("", "checkpoint-Test")
   173  	assert.NoError(t, err)
   174  	defer func() { _ = os.RemoveAll(ckDir) }()
   175  
   176  	conf := generateTestConfiguration(ckDir)
   177  	metaServer, err := generateTestMetaServer(conf, pods)
   178  	assert.NoError(t, err)
   179  	metamanager := metamanager.NewManager(metrics.DummyMetrics{}, nil, metaServer)
   180  
   181  	checkpointManager, err := checkpointmanager.NewCheckpointManager("/tmp/reconcile")
   182  	assert.NoError(t, err)
   183  
   184  	m := &ManagerImpl{
   185  		endpoints:   map[string]endpoint.EndpointInfo{},
   186  		socketdir:   "/tmp/reconcile",
   187  		metaManager: metamanager,
   188  		resourceNamesMap: map[string]string{
   189  			"domain1.com/resource1": "domain1.com/resource1",
   190  		},
   191  		podResources:      newPodResourcesChk(),
   192  		resourceExecutor:  executor.NewExecutor(&cgroupmgr.FakeCgroupManager{}),
   193  		checkpointManager: checkpointManager,
   194  		podAddChan:        make(chan string, 1),
   195  		podDeleteChan:     make(chan string, 1),
   196  		qosConfig:         generic.NewQoSConfiguration(),
   197  	}
   198  	defer func() { _ = os.Remove("/tmp/reconcile/kubelet_qrm_checkpoint") }()
   199  	topologyManager, _ := topology.NewManager([]cadvisorapi.Node{
   200  		{
   201  			Id: 0,
   202  		},
   203  	}, "none", nil)
   204  	topologyManager.AddHintProvider(m)
   205  	m.topologyManager = topologyManager
   206  	err = registerEndpointByPods(m, pods)
   207  	assert.NoError(t, err)
   208  
   209  	m.reconcile()
   210  
   211  	assert.Equal(t, len(m.podResources.pods()), 2)
   212  	for _, pod := range pods {
   213  		containerResources := m.podResources.podResources(string(pod.UID))
   214  		assert.NotNil(t, containerResources)
   215  
   216  		for _, resourceAllocation := range containerResources {
   217  			assert.Equal(t, len(resourceAllocation), 2)
   218  		}
   219  	}
   220  }
   221  
   222  func TestIsSkippedContainer(t *testing.T) {
   223  	t.Parallel()
   224  
   225  	testCases := []struct {
   226  		Name      string
   227  		Pod       *v1.Pod
   228  		Container *v1.Container
   229  		Expected  bool
   230  	}{
   231  		{
   232  			Name: "mainContainer",
   233  			Pod: &v1.Pod{
   234  				Spec: v1.PodSpec{
   235  					Containers: []v1.Container{
   236  						{
   237  							Name: "testContainer",
   238  						},
   239  					},
   240  				},
   241  			},
   242  			Container: &v1.Container{
   243  				Name: "testContainer",
   244  			},
   245  			Expected: false,
   246  		},
   247  		{
   248  			Name: "initContainer",
   249  			Pod: &v1.Pod{
   250  				Spec: v1.PodSpec{
   251  					InitContainers: []v1.Container{
   252  						{
   253  							Name: "testContainer",
   254  						},
   255  					},
   256  				},
   257  			},
   258  			Container: &v1.Container{
   259  				Name: "testContainer",
   260  			},
   261  			Expected: true,
   262  		},
   263  		{
   264  			Name:      "fail",
   265  			Pod:       nil,
   266  			Container: nil,
   267  			Expected:  false,
   268  		},
   269  	}
   270  
   271  	for _, tc := range testCases {
   272  		tc := tc
   273  		t.Run(tc.Name, func(t *testing.T) {
   274  			t.Parallel()
   275  			res := isSkippedContainer(tc.Pod, tc.Container)
   276  			assert.Equal(t, res, tc.Expected)
   277  		})
   278  	}
   279  }
   280  
   281  func TestGetMappedResourceName(t *testing.T) {
   282  	t.Parallel()
   283  
   284  	m := &ManagerImpl{
   285  		resourceNamesMap: map[string]string{
   286  			"test/cpu":    "cpu",
   287  			"test/memory": "memory",
   288  		},
   289  	}
   290  
   291  	testCases := []struct {
   292  		Name           string
   293  		resourceName   string
   294  		requests       v1.ResourceList
   295  		expectErr      bool
   296  		expectResource string
   297  	}{
   298  		{
   299  			Name:         "cpu",
   300  			resourceName: "test/cpu",
   301  			requests: map[v1.ResourceName]resource.Quantity{
   302  				"cpu": *resource.NewQuantity(1, resource.DecimalSI),
   303  			},
   304  			expectErr:      false,
   305  			expectResource: "cpu",
   306  		},
   307  		{
   308  			Name:         "not found",
   309  			resourceName: "cpu",
   310  			requests: map[v1.ResourceName]resource.Quantity{
   311  				"cpu": *resource.NewQuantity(1, resource.DecimalSI),
   312  			},
   313  			expectErr:      false,
   314  			expectResource: "cpu",
   315  		},
   316  		{
   317  			Name:         "repetition",
   318  			resourceName: "test/cpu",
   319  			requests: map[v1.ResourceName]resource.Quantity{
   320  				"cpu":      *resource.NewQuantity(1, resource.DecimalSI),
   321  				"test/cpu": *resource.NewQuantity(1, resource.DecimalSI),
   322  			},
   323  			expectErr:      true,
   324  			expectResource: "cpu",
   325  		},
   326  	}
   327  
   328  	for _, tc := range testCases {
   329  		tc := tc
   330  		t.Run(tc.Name, func(t *testing.T) {
   331  			t.Parallel()
   332  			r, err := m.getMappedResourceName(tc.resourceName, tc.requests)
   333  			if tc.expectErr {
   334  				assert.NotNil(t, err)
   335  			} else {
   336  				assert.Nil(t, err)
   337  				assert.Equal(t, r, tc.expectResource)
   338  			}
   339  		})
   340  	}
   341  }
   342  
   343  func TestRun(t *testing.T) {
   344  	t.Parallel()
   345  
   346  	pods := []*v1.Pod{
   347  		makePod("testPod1", v1.ResourceList{
   348  			"cpu":    *resource.NewQuantity(2, resource.DecimalSI),
   349  			"memory": *resource.NewQuantity(2, resource.DecimalSI),
   350  		}),
   351  		makePod("testPod2", v1.ResourceList{
   352  			"cpu":    *resource.NewQuantity(2, resource.DecimalSI),
   353  			"memory": *resource.NewQuantity(2, resource.DecimalSI),
   354  		}),
   355  	}
   356  
   357  	ckDir, err := ioutil.TempDir("", "checkpoint-Test")
   358  	assert.NoError(t, err)
   359  	defer func() { _ = os.RemoveAll(ckDir) }()
   360  
   361  	conf := generateTestConfiguration(ckDir)
   362  	metaServer, err := generateTestMetaServer(conf, pods)
   363  	assert.NoError(t, err)
   364  
   365  	checkpointManager, err := checkpointmanager.NewCheckpointManager("/tmp/run")
   366  	assert.NoError(t, err)
   367  
   368  	m := &ManagerImpl{
   369  		reconcilePeriod: 2 * time.Second,
   370  		endpoints:       map[string]endpoint.EndpointInfo{},
   371  		socketdir:       "/tmp/run",
   372  		socketname:      "tmp.sock",
   373  		resourceNamesMap: map[string]string{
   374  			"domain1.com/resource1": "domain1.com/resource1",
   375  		},
   376  		podResources:      newPodResourcesChk(),
   377  		resourceExecutor:  executor.NewExecutor(&cgroupmgr.FakeCgroupManager{}),
   378  		checkpointManager: checkpointManager,
   379  		podAddChan:        make(chan string, 1),
   380  		podDeleteChan:     make(chan string, 1),
   381  		qosConfig:         generic.NewQoSConfiguration(),
   382  		podResourceSocket: "unix:/tmp/run/podresource.sock",
   383  	}
   384  	defer func() { _ = os.RemoveAll("/tmp/run") }()
   385  	metaManager := metamanager.NewManager(metrics.DummyMetrics{}, m.podResources.pods, metaServer)
   386  	m.metaManager = metaManager
   387  
   388  	topologyManager, _ := topology.NewManager([]cadvisorapi.Node{
   389  		{
   390  			Id: 0,
   391  		},
   392  	}, "none", nil)
   393  	topologyManager.AddHintProvider(m)
   394  	m.topologyManager = topologyManager
   395  
   396  	err = registerEndpointByPods(m, pods)
   397  	assert.NoError(t, err)
   398  
   399  	ctx, cancel := context.WithCancel(context.Background())
   400  	defer cancel()
   401  
   402  	m.Run(ctx)
   403  	time.Sleep(5 * time.Second)
   404  
   405  	assert.Equal(t, len(m.podResources.pods()), 2)
   406  	assert.Equal(t, len(m.podResources.allAllocatedResourceNames()), 2)
   407  }
   408  
   409  type TestResource struct {
   410  	resourceName     string
   411  	resourceQuantity resource.Quantity
   412  }
   413  
   414  func generateTestMetaServer(conf *config.Configuration, podList []*v1.Pod) (*metaserver.MetaServer, error) {
   415  	genericCtx, err := katalyst_base.GenerateFakeGenericContext([]runtime.Object{})
   416  	if err != nil {
   417  		return nil, err
   418  	}
   419  
   420  	ms, err := metaserver.NewMetaServer(genericCtx.Client, metrics.DummyMetrics{}, conf)
   421  	if err != nil {
   422  		return ms, err
   423  	}
   424  	ms.PodFetcher = &pod.PodFetcherStub{
   425  		PodList: podList,
   426  	}
   427  	return ms, nil
   428  }
   429  
   430  func generateTestConfiguration(checkpointDir string) *config.Configuration {
   431  	conf, _ := options.NewOptions().Config()
   432  
   433  	conf.MetaServerConfiguration.CheckpointManagerDir = checkpointDir
   434  
   435  	return conf
   436  }
   437  
   438  func makePod(name string, rl v1.ResourceList) *v1.Pod {
   439  	return &v1.Pod{
   440  		ObjectMeta: metav1.ObjectMeta{
   441  			UID:  uuid.NewUUID(),
   442  			Name: name,
   443  		},
   444  		Spec: v1.PodSpec{
   445  			Containers: []v1.Container{
   446  				{
   447  					Name: name,
   448  					Resources: v1.ResourceRequirements{
   449  						Requests: rl.DeepCopy(),
   450  						Limits:   rl.DeepCopy(),
   451  					},
   452  				},
   453  			},
   454  		},
   455  	}
   456  }
   457  
   458  func registerEndpointByRes(manager *ManagerImpl, testRes []TestResource) error {
   459  	if manager == nil {
   460  		return fmt.Errorf("registerEndpointByRes got nil manager")
   461  	}
   462  
   463  	for i, res := range testRes {
   464  		var OciPropertyName string
   465  		if res.resourceName == "domain1.com/resource1" {
   466  			OciPropertyName = "CpusetCpus"
   467  		} else if res.resourceName == "domain2.com/resource2" {
   468  			OciPropertyName = "CpusetMems"
   469  		}
   470  
   471  		curResourceName := res.resourceName
   472  
   473  		if res.resourceName == "domain1.com/resource1" || res.resourceName == "domain2.com/resource2" {
   474  			manager.registerEndpoint(curResourceName, &pluginapi.ResourcePluginOptions{
   475  				PreStartRequired:      true,
   476  				WithTopologyAlignment: true,
   477  				NeedReconcile:         true,
   478  			}, &MockEndpoint{
   479  				allocateFunc: func(req *pluginapi.ResourceRequest) (*pluginapi.ResourceAllocationResponse, error) {
   480  					if req == nil {
   481  						return nil, fmt.Errorf("allocateFunc got nil request")
   482  					}
   483  
   484  					resp := new(pluginapi.ResourceAllocationResponse)
   485  					resp.AllocationResult = new(pluginapi.ResourceAllocation)
   486  					resp.AllocationResult.ResourceAllocation = make(map[string]*pluginapi.ResourceAllocationInfo)
   487  					resp.AllocationResult.ResourceAllocation[curResourceName] = new(pluginapi.ResourceAllocationInfo)
   488  					resp.AllocationResult.ResourceAllocation[curResourceName].Envs = make(map[string]string)
   489  					resp.AllocationResult.ResourceAllocation[curResourceName].Envs[fmt.Sprintf("key%d", i)] = fmt.Sprintf("val%d", i)
   490  					resp.AllocationResult.ResourceAllocation[curResourceName].Annotations = make(map[string]string)
   491  					resp.AllocationResult.ResourceAllocation[curResourceName].Annotations[fmt.Sprintf("key%d", i)] = fmt.Sprintf("val%d", i)
   492  					resp.AllocationResult.ResourceAllocation[curResourceName].IsScalarResource = true
   493  					resp.AllocationResult.ResourceAllocation[curResourceName].IsNodeResource = true
   494  					resp.AllocationResult.ResourceAllocation[curResourceName].AllocatedQuantity = req.ResourceRequests[curResourceName]
   495  					resp.AllocationResult.ResourceAllocation[curResourceName].AllocationResult = "0-1"
   496  					resp.AllocationResult.ResourceAllocation[curResourceName].OciPropertyName = OciPropertyName
   497  					return resp, nil
   498  				},
   499  				topologyHints: []*pluginapi.TopologyHint{
   500  					{
   501  						Nodes:     []uint64{0},
   502  						Preferred: true,
   503  					},
   504  				},
   505  			})
   506  		} else if res.resourceName == "domain3.com/resource3" {
   507  			manager.registerEndpoint(curResourceName, &pluginapi.ResourcePluginOptions{
   508  				PreStartRequired:      true,
   509  				WithTopologyAlignment: true,
   510  				NeedReconcile:         true,
   511  			}, &MockEndpoint{
   512  				allocateFunc: func(req *pluginapi.ResourceRequest) (*pluginapi.ResourceAllocationResponse, error) {
   513  					return nil, fmt.Errorf("mock error")
   514  				},
   515  				topologyHints: []*pluginapi.TopologyHint{
   516  					{
   517  						Nodes:     []uint64{0},
   518  						Preferred: true,
   519  					},
   520  				},
   521  			})
   522  		}
   523  	}
   524  
   525  	return nil
   526  }
   527  
   528  func registerEndpointByPods(manager *ManagerImpl, pods []*v1.Pod) error {
   529  	for _, resource := range []string{"cpu", "memory"} {
   530  		resp := &pluginapi.GetResourcesAllocationResponse{
   531  			PodResources: map[string]*pluginapi.ContainerResources{},
   532  		}
   533  		for _, pod := range pods {
   534  			uid := string(pod.UID)
   535  			if _, ok := resp.PodResources[uid]; !ok {
   536  				resp.PodResources[uid] = &pluginapi.ContainerResources{
   537  					ContainerResources: map[string]*pluginapi.ResourceAllocation{},
   538  				}
   539  			}
   540  			for _, container := range pod.Spec.Containers {
   541  				if _, ok := resp.PodResources[uid].ContainerResources[container.Name]; !ok {
   542  					resp.PodResources[uid].ContainerResources[container.Name] = &pluginapi.ResourceAllocation{
   543  						ResourceAllocation: map[string]*pluginapi.ResourceAllocationInfo{},
   544  					}
   545  				}
   546  
   547  				for resourceName, quantity := range container.Resources.Requests {
   548  					if resourceName.String() == resource {
   549  						resp.PodResources[uid].ContainerResources[container.Name].ResourceAllocation[string(resourceName)] = &pluginapi.ResourceAllocationInfo{
   550  							IsNodeResource:    true,
   551  							IsScalarResource:  false,
   552  							AllocatedQuantity: float64(quantity.Value()),
   553  							AllocationResult:  "0-1",
   554  						}
   555  					}
   556  				}
   557  			}
   558  		}
   559  
   560  		manager.registerEndpoint(resource, &pluginapi.ResourcePluginOptions{
   561  			NeedReconcile: true,
   562  		}, &MockEndpoint{
   563  			resourceAlloc: func(ctx context.Context, request *pluginapi.GetResourcesAllocationRequest) (*pluginapi.GetResourcesAllocationResponse, error) {
   564  				return resp, nil
   565  			},
   566  			allocateFunc: func(resourceRequest *pluginapi.ResourceRequest) (*pluginapi.ResourceAllocationResponse, error) {
   567  				return &pluginapi.ResourceAllocationResponse{}, nil
   568  			},
   569  			topologyHints: []*pluginapi.TopologyHint{
   570  				{
   571  					Nodes:     []uint64{0},
   572  					Preferred: true,
   573  				},
   574  			},
   575  		})
   576  	}
   577  
   578  	return nil
   579  }
   580  
   581  /* ------------------  mock endpoint for test  ----------------------- */
   582  type MockEndpoint struct {
   583  	allocateFunc                             func(resourceRequest *pluginapi.ResourceRequest) (*pluginapi.ResourceAllocationResponse, error)
   584  	resourceAlloc                            func(ctx context.Context, request *pluginapi.GetResourcesAllocationRequest) (*pluginapi.GetResourcesAllocationResponse, error)
   585  	getTopologyAwareResourcesFunc            func(c context.Context, request *pluginapi.GetTopologyAwareResourcesRequest) (*pluginapi.GetTopologyAwareResourcesResponse, error)
   586  	getTopologyAwareAllocatableResourcesFunc func(c context.Context, request *pluginapi.GetTopologyAwareAllocatableResourcesRequest) (*pluginapi.GetTopologyAwareAllocatableResourcesResponse, error)
   587  	stopTime                                 time.Time
   588  	topologyHints                            []*pluginapi.TopologyHint
   589  }
   590  
   591  func (m *MockEndpoint) Stop() {
   592  	m.stopTime = time.Now()
   593  }
   594  func (m *MockEndpoint) run(success chan<- bool) {}
   595  
   596  func (m *MockEndpoint) Allocate(ctx context.Context, resourceRequest *pluginapi.ResourceRequest) (*pluginapi.ResourceAllocationResponse, error) {
   597  	if m.IsStopped() {
   598  		return nil, fmt.Errorf("endpoint %v has been stopped", m)
   599  	}
   600  	if m.allocateFunc != nil {
   601  		return m.allocateFunc(resourceRequest)
   602  	}
   603  	return nil, nil
   604  }
   605  
   606  func (m *MockEndpoint) GetTopologyHints(c context.Context, resourceRequest *pluginapi.ResourceRequest) (*pluginapi.ResourceHintsResponse, error) {
   607  	return &pluginapi.ResourceHintsResponse{
   608  		PodUid:         resourceRequest.PodUid,
   609  		PodNamespace:   resourceRequest.PodNamespace,
   610  		PodName:        resourceRequest.PodName,
   611  		ContainerName:  resourceRequest.ContainerName,
   612  		ContainerIndex: resourceRequest.ContainerIndex,
   613  		ContainerType:  resourceRequest.ContainerType,
   614  		PodRole:        resourceRequest.PodRole,
   615  		PodType:        resourceRequest.PodType,
   616  		ResourceName:   resourceRequest.ResourceName,
   617  		Labels:         resourceRequest.Labels,
   618  		Annotations:    resourceRequest.Annotations,
   619  		ResourceHints: map[string]*pluginapi.ListOfTopologyHints{
   620  			resourceRequest.ResourceName: {
   621  				Hints: m.topologyHints,
   622  			},
   623  		},
   624  	}, nil
   625  }
   626  
   627  func (m *MockEndpoint) IsStopped() bool {
   628  	return !m.stopTime.IsZero()
   629  }
   630  
   631  var SGP int = 0
   632  
   633  func (m *MockEndpoint) StopGracePeriodExpired() bool {
   634  	if SGP == 0 {
   635  		return false
   636  	} else {
   637  		return true
   638  	}
   639  }
   640  
   641  func (m *MockEndpoint) RemovePod(ctx context.Context, removePodRequest *pluginapi.RemovePodRequest) (*pluginapi.RemovePodResponse, error) {
   642  	return nil, nil
   643  }
   644  
   645  func (m *MockEndpoint) GetResourceAllocation(ctx context.Context, request *pluginapi.GetResourcesAllocationRequest) (*pluginapi.GetResourcesAllocationResponse, error) {
   646  	if m.resourceAlloc != nil {
   647  		return m.resourceAlloc(ctx, request)
   648  	}
   649  	return nil, nil
   650  }
   651  
   652  func (m *MockEndpoint) GetResourcePluginOptions(ctx context.Context, in *pluginapi.Empty, opts ...grpc.CallOption) (*pluginapi.ResourcePluginOptions, error) {
   653  	return &pluginapi.ResourcePluginOptions{
   654  		NeedReconcile: true,
   655  	}, nil
   656  }
   657  
   658  func (m *MockEndpoint) GetTopologyAwareResources(c context.Context, request *pluginapi.GetTopologyAwareResourcesRequest) (*pluginapi.GetTopologyAwareResourcesResponse, error) {
   659  	if m.getTopologyAwareResourcesFunc != nil {
   660  		return m.getTopologyAwareResourcesFunc(c, request)
   661  	}
   662  	return nil, nil
   663  }
   664  
   665  func (m *MockEndpoint) GetTopologyAwareAllocatableResources(c context.Context, request *pluginapi.GetTopologyAwareAllocatableResourcesRequest) (*pluginapi.GetTopologyAwareAllocatableResourcesResponse, error) {
   666  	if m.getTopologyAwareAllocatableResourcesFunc != nil {
   667  		return m.getTopologyAwareAllocatableResourcesFunc(c, request)
   668  	}
   669  	return nil, nil
   670  }