mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-18 04:54:54 +00:00
test(ut/dra): add unit test for pod requesting prepared and new claims
This commit is contained in:
@@ -65,8 +65,9 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
shareID = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
shareUID = types.UID(shareID)
|
||||
shareID = "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
|
||||
shareUID = types.UID(shareID)
|
||||
testPodCounter atomic.Uint32
|
||||
)
|
||||
|
||||
type fakeDRADriverGRPCServer struct {
|
||||
@@ -300,6 +301,23 @@ func setupFakeDRADriverGRPCServer(ctx context.Context, shouldTimeout bool, plugi
|
||||
}, nil
|
||||
}
|
||||
|
||||
func genPrepareResourcesResponse(claimUID types.UID) *drapb.NodePrepareResourcesResponse {
|
||||
return &drapb.NodePrepareResourcesResponse{
|
||||
Claims: map[string]*drapb.NodePrepareResourceResponse{
|
||||
string(claimUID): {
|
||||
Devices: []*drapb.Device{
|
||||
{
|
||||
PoolName: poolName,
|
||||
DeviceName: deviceName,
|
||||
RequestNames: []string{requestName},
|
||||
CdiDeviceIds: []string{cdiID},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewManagerImpl(t *testing.T) {
|
||||
kubeClient := fake.NewSimpleClientset()
|
||||
for _, test := range []struct {
|
||||
@@ -363,6 +381,45 @@ func genTestPod() *v1.Pod {
|
||||
}
|
||||
}
|
||||
|
||||
func genTestPodWithClaims(claimNames ...string) *v1.Pod {
|
||||
podCounter := testPodCounter.Add(1)
|
||||
|
||||
podName := fmt.Sprintf("test-pod-%d", podCounter)
|
||||
podUID := types.UID(fmt.Sprintf("test-pod-uid-%d", podCounter))
|
||||
|
||||
resourceClaims := make([]v1.PodResourceClaim, 0, len(claimNames))
|
||||
containerClaims := make([]v1.ResourceClaim, 0, len(claimNames))
|
||||
|
||||
for _, claimName := range claimNames {
|
||||
cn := claimName
|
||||
resourceClaims = append(resourceClaims, v1.PodResourceClaim{
|
||||
Name: cn,
|
||||
ResourceClaimName: &cn,
|
||||
})
|
||||
containerClaims = append(containerClaims, v1.ResourceClaim{
|
||||
Name: cn,
|
||||
})
|
||||
}
|
||||
|
||||
return &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: podName,
|
||||
Namespace: namespace,
|
||||
UID: podUID,
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
ResourceClaims: resourceClaims,
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Resources: v1.ResourceRequirements{
|
||||
Claims: containerClaims,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// genTestPodWithExtendedResource generates pod object
|
||||
func genTestPodWithExtendedResource() *v1.Pod {
|
||||
return &v1.Pod{
|
||||
@@ -787,18 +844,7 @@ dra_operations_duration_seconds_sum{is_error="false",operation_name="PrepareReso
|
||||
dra_operations_duration_seconds_count{is_error="false",operation_name="PrepareResources"} 1
|
||||
`,
|
||||
expectedClaimInfoState: genClaimInfoState(cdiID),
|
||||
resp: &drapb.NodePrepareResourcesResponse{Claims: map[string]*drapb.NodePrepareResourceResponse{
|
||||
string(claimUID): {
|
||||
Devices: []*drapb.Device{
|
||||
{
|
||||
PoolName: poolName,
|
||||
DeviceName: deviceName,
|
||||
RequestNames: []string{requestName},
|
||||
CdiDeviceIds: []string{cdiID},
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
resp: genPrepareResourcesResponse(claimUID),
|
||||
},
|
||||
{
|
||||
description: "resource already prepared",
|
||||
@@ -807,18 +853,7 @@ dra_operations_duration_seconds_count{is_error="false",operation_name="PrepareRe
|
||||
claim: genTestClaim(claimName, driverName, deviceName, podUID),
|
||||
claimInfo: genTestClaimInfo(claimUID, []string{podUID}, true),
|
||||
expectedClaimInfoState: genClaimInfoState(cdiID),
|
||||
resp: &drapb.NodePrepareResourcesResponse{Claims: map[string]*drapb.NodePrepareResourceResponse{
|
||||
string(claimUID): {
|
||||
Devices: []*drapb.Device{
|
||||
{
|
||||
PoolName: poolName,
|
||||
DeviceName: deviceName,
|
||||
RequestNames: []string{requestName},
|
||||
CdiDeviceIds: []string{cdiID},
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
resp: genPrepareResourcesResponse(claimUID),
|
||||
expectedMetric: `# HELP dra_operations_duration_seconds [ALPHA] Latency histogram in seconds for the duration of handling all ResourceClaims referenced by a pod when the pod starts or stops. Identified by the name of the operation (PrepareResources or UnprepareResources) and separated by the success of the operation. The number of failed operations is provided through the histogram's overall count.
|
||||
# TYPE dra_operations_duration_seconds histogram
|
||||
dra_operations_duration_seconds_bucket{is_error="false",operation_name="PrepareResources",le="+Inf"} 1
|
||||
@@ -852,19 +887,8 @@ dra_operations_duration_seconds_count{is_error="true",operation_name="PrepareRes
|
||||
pod: genTestPod(),
|
||||
claim: genTestClaim(claimName, driverName, deviceName, podUID),
|
||||
expectedClaimInfoState: genClaimInfoState(cdiID),
|
||||
resp: &drapb.NodePrepareResourcesResponse{Claims: map[string]*drapb.NodePrepareResourceResponse{
|
||||
string(claimUID): {
|
||||
Devices: []*drapb.Device{
|
||||
{
|
||||
PoolName: poolName,
|
||||
DeviceName: deviceName,
|
||||
RequestNames: []string{requestName},
|
||||
CdiDeviceIds: []string{cdiID},
|
||||
},
|
||||
},
|
||||
},
|
||||
}},
|
||||
expectedPrepareCalls: 1,
|
||||
resp: genPrepareResourcesResponse(claimUID),
|
||||
expectedPrepareCalls: 1,
|
||||
expectedMetric: `# HELP dra_grpc_operations_duration_seconds [ALPHA] Duration in seconds of the DRA gRPC operations
|
||||
# TYPE dra_grpc_operations_duration_seconds histogram
|
||||
dra_grpc_operations_duration_seconds_bucket{driver_name="test-driver",grpc_status_code="OK",method_name="/k8s.io.kubelet.pkg.apis.dra.v1.DRAPlugin/NodePrepareResources",le="+Inf"} 1
|
||||
@@ -1053,6 +1077,74 @@ dra_operations_duration_seconds_count{is_error="false",operation_name="PrepareRe
|
||||
}
|
||||
}
|
||||
|
||||
// TestPrepareResourcesWithPreparedAndNewClaim verifies that PrepareResources
|
||||
// correctly handles a pod that references a mix of ResourceClaims:
|
||||
// - first claim already prepared by a previous pod
|
||||
// - second claim is new and needs to be prepared
|
||||
func TestPrepareResourcesWithPreparedAndNewClaim(t *testing.T) {
|
||||
logger, tCtx := ktesting.NewTestContext(t)
|
||||
fakeKubeClient := fake.NewClientset()
|
||||
|
||||
manager, err := NewManager(logger, fakeKubeClient, t.TempDir())
|
||||
require.NoError(t, err)
|
||||
manager.initDRAPluginManager(tCtx, getFakeNode, time.Second)
|
||||
|
||||
secondClaimName := fmt.Sprintf("%s-second", claimName)
|
||||
|
||||
// Generate two pods where the second pod reuses an existing claim and adds a new one
|
||||
firstPod := genTestPodWithClaims(claimName)
|
||||
secondPod := genTestPodWithClaims(claimName, secondClaimName)
|
||||
|
||||
firstClaim := genTestClaim(claimName, driverName, deviceName, string(firstPod.ObjectMeta.UID))
|
||||
secondClaim := genTestClaim(secondClaimName, driverName, deviceName, string(secondPod.ObjectMeta.UID))
|
||||
|
||||
// Make firstClaim reserved for first and second pod
|
||||
firstClaim.Status.ReservedFor = append(
|
||||
firstClaim.Status.ReservedFor,
|
||||
resourceapi.ResourceClaimConsumerReference{UID: secondPod.ObjectMeta.UID},
|
||||
)
|
||||
|
||||
_, err = fakeKubeClient.ResourceV1().ResourceClaims(namespace).Create(tCtx, firstClaim, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = fakeKubeClient.ResourceV1().ResourceClaims(namespace).Create(tCtx, secondClaim, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
respFirst := genPrepareResourcesResponse(firstClaim.UID)
|
||||
draServerInfo, err := setupFakeDRADriverGRPCServer(tCtx, false, nil, respFirst, nil, nil)
|
||||
require.NoError(t, err)
|
||||
defer draServerInfo.teardownFn()
|
||||
|
||||
plg := manager.GetWatcherHandler()
|
||||
require.NoError(t, plg.RegisterPlugin(driverName, draServerInfo.socketName, []string{drapb.DRAPluginService}, nil))
|
||||
|
||||
err = manager.PrepareResources(tCtx, firstPod)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, uint32(1),
|
||||
draServerInfo.server.prepareResourceCalls.Load(),
|
||||
"first pod should trigger one prepare call",
|
||||
)
|
||||
|
||||
respSecond := genPrepareResourcesResponse(secondClaim.UID)
|
||||
draServerInfo.server.prepareResourcesResponse = respSecond
|
||||
|
||||
err = manager.PrepareResources(tCtx, secondPod)
|
||||
require.NoError(t, err)
|
||||
|
||||
// second pod triggered exactly one prepare call (new claim only) + previous one call
|
||||
assert.Equal(t, uint32(2),
|
||||
draServerInfo.server.prepareResourceCalls.Load(),
|
||||
"second pod should trigger one prepare call for the new claim",
|
||||
)
|
||||
|
||||
for _, claimName := range []string{firstClaim.Name, secondClaim.Name} {
|
||||
claimInfo, exists := manager.cache.get(claimName, namespace)
|
||||
require.True(t, exists, "claim %s should exist in cache", claimName)
|
||||
assert.True(t, claimInfo.prepared, "claim %s should be marked as prepared", claimName)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnprepareResources(t *testing.T) {
|
||||
fakeKubeClient := fake.NewSimpleClientset()
|
||||
for _, test := range []struct {
|
||||
|
||||
Reference in New Issue
Block a user