Skip to content

Commit 34a64db

Browse files
committed
extended resource backed by DRA: implementation
1 parent 3068b60 commit 34a64db

File tree

34 files changed

+2753
-151
lines changed

34 files changed

+2753
-151
lines changed

pkg/api/pod/util.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,10 @@ func dropDisabledPodStatusFields(podStatus, oldPodStatus *api.PodStatus, podSpec
10091009
podStatus.ResourceClaimStatuses = nil
10101010
}
10111011

1012+
if !utilfeature.DefaultFeatureGate.Enabled(features.DRAExtendedResource) && !draExendedResourceInUse(oldPodStatus) {
1013+
podStatus.ExtendedResourceClaimStatus = nil
1014+
}
1015+
10121016
if !utilfeature.DefaultFeatureGate.Enabled(features.RecursiveReadOnlyMounts) && !rroInUse(oldPodSpec) {
10131017
for i := range podStatus.ContainerStatuses {
10141018
podStatus.ContainerStatuses[i].VolumeMounts = nil
@@ -1064,15 +1068,21 @@ func dropDisabledDynamicResourceAllocationFields(podSpec, oldPodSpec *api.PodSpe
10641068
}
10651069
}
10661070

1067-
func dynamicResourceAllocationInUse(podSpec *api.PodSpec) bool {
1068-
if podSpec == nil {
1069-
return false
1071+
func draExendedResourceInUse(podStatus *api.PodStatus) bool {
1072+
if podStatus != nil && podStatus.ExtendedResourceClaimStatus != nil {
1073+
return true
10701074
}
1075+
return false
1076+
}
10711077

1078+
func dynamicResourceAllocationInUse(podSpec *api.PodSpec) bool {
10721079
// We only need to check this field because the containers cannot have
10731080
// resource requirements entries for claims without a corresponding
10741081
// entry at the pod spec level.
1075-
return len(podSpec.ResourceClaims) > 0
1082+
if podSpec != nil && len(podSpec.ResourceClaims) > 0 {
1083+
return true
1084+
}
1085+
return false
10761086
}
10771087

10781088
func dropResourceClaimRequests(containers []api.Container) {

pkg/api/pod/util_test.go

Lines changed: 74 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -895,15 +895,35 @@ func TestDropDynamicResourceAllocation(t *testing.T) {
895895
EphemeralContainers: []api.EphemeralContainer{{}},
896896
},
897897
}
898+
podWithExtendedResource := &api.Pod{
899+
Spec: api.PodSpec{
900+
Containers: []api.Container{{}},
901+
InitContainers: []api.Container{{}},
902+
EphemeralContainers: []api.EphemeralContainer{{}},
903+
},
904+
Status: api.PodStatus{
905+
ExtendedResourceClaimStatus: &api.PodExtendedResourceClaimStatus{
906+
ResourceClaimName: "resource-claim-name",
907+
RequestMappings: []api.ContainerExtendedResourceRequest{
908+
{
909+
ContainerName: "c",
910+
ResourceName: "e",
911+
RequestName: "c-0-r-0",
912+
},
913+
},
914+
},
915+
},
916+
}
898917

899918
var noPod *api.Pod
900919

901920
testcases := []struct {
902-
description string
903-
enabled bool
904-
oldPod *api.Pod
905-
newPod *api.Pod
906-
wantPod *api.Pod
921+
description string
922+
enabled bool
923+
extendedEnabled bool
924+
oldPod *api.Pod
925+
newPod *api.Pod
926+
wantPod *api.Pod
907927
}{
908928
{
909929
description: "old with claims / new with claims / disabled",
@@ -986,11 +1006,60 @@ func TestDropDynamicResourceAllocation(t *testing.T) {
9861006
newPod: podWithoutClaims,
9871007
wantPod: podWithoutClaims,
9881008
},
1009+
{
1010+
description: "extended resource / no old pod/ new with extended resource / disabled",
1011+
enabled: false,
1012+
extendedEnabled: false,
1013+
oldPod: noPod,
1014+
newPod: podWithExtendedResource,
1015+
wantPod: podWithoutClaims,
1016+
},
1017+
{
1018+
description: "extended resource / old without claim / new with extended resource / disabled",
1019+
enabled: false,
1020+
extendedEnabled: false,
1021+
oldPod: podWithoutClaims,
1022+
newPod: podWithExtendedResource,
1023+
wantPod: podWithoutClaims,
1024+
},
1025+
{
1026+
description: "extended resource / no old pod/ new with extended resource / extended disabled only",
1027+
enabled: true,
1028+
extendedEnabled: false,
1029+
oldPod: noPod,
1030+
newPod: podWithExtendedResource,
1031+
wantPod: podWithoutClaims,
1032+
},
1033+
{
1034+
description: "extended resource / old without claim / new with extended resource / extended disabled only",
1035+
enabled: true,
1036+
extendedEnabled: false,
1037+
oldPod: podWithoutClaims,
1038+
newPod: podWithExtendedResource,
1039+
wantPod: podWithoutClaims,
1040+
},
1041+
{
1042+
description: "extended resource / no old pod/ new with extended resource / enabled",
1043+
enabled: true,
1044+
extendedEnabled: true,
1045+
oldPod: noPod,
1046+
newPod: podWithExtendedResource,
1047+
wantPod: podWithExtendedResource,
1048+
},
1049+
{
1050+
description: "extended resource / old without claim / new with extended resource / enabled",
1051+
enabled: true,
1052+
extendedEnabled: true,
1053+
oldPod: podWithoutClaims,
1054+
newPod: podWithExtendedResource,
1055+
wantPod: podWithExtendedResource,
1056+
},
9891057
}
9901058

9911059
for _, tc := range testcases {
9921060
t.Run(tc.description, func(t *testing.T) {
9931061
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DynamicResourceAllocation, tc.enabled)
1062+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.DRAExtendedResource, tc.extendedEnabled)
9941063

9951064
oldPod := tc.oldPod.DeepCopy()
9961065
newPod := tc.newPod.DeepCopy()

pkg/apis/core/validation/validation.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5873,6 +5873,7 @@ func ValidatePodStatusUpdate(newPod, oldPod *core.Pod, opts PodValidationOptions
58735873
allErrs = append(allErrs, ValidateInitContainerStateTransition(newPod.Status.InitContainerStatuses, oldPod.Status.InitContainerStatuses, fldPath.Child("initContainerStatuses"), &oldPod.Spec)...)
58745874
allErrs = append(allErrs, ValidateEphemeralContainerStateTransition(newPod.Status.EphemeralContainerStatuses, oldPod.Status.EphemeralContainerStatuses, fldPath.Child("ephemeralContainerStatuses"))...)
58755875
allErrs = append(allErrs, validatePodResourceClaimStatuses(newPod.Status.ResourceClaimStatuses, newPod.Spec.ResourceClaims, fldPath.Child("resourceClaimStatuses"))...)
5876+
allErrs = append(allErrs, validatePodExtendedResourceClaimStatus(newPod.Status.ExtendedResourceClaimStatus, &newPod.Spec, fldPath.Child("extendedResourceClaimStatus"))...)
58765877

58775878
if newIPErrs := validatePodIPs(newPod, oldPod); len(newIPErrs) > 0 {
58785879
allErrs = append(allErrs, newIPErrs...)
@@ -5941,6 +5942,58 @@ func validatePodResourceClaimStatuses(statuses []core.PodResourceClaimStatus, po
59415942
return allErrs
59425943
}
59435944

5945+
// validatePodExtendedResourceClaimStatus validates the ExtendedResourceClaimStatus in a pod status.
5946+
func validatePodExtendedResourceClaimStatus(status *core.PodExtendedResourceClaimStatus, spec *core.PodSpec, fldPath *field.Path) field.ErrorList {
5947+
if status == nil {
5948+
return nil
5949+
}
5950+
5951+
containers := make(map[string]*core.Container)
5952+
for _, c := range spec.InitContainers {
5953+
containers[c.Name] = &c
5954+
}
5955+
for _, c := range spec.Containers {
5956+
containers[c.Name] = &c
5957+
}
5958+
5959+
var allErrs field.ErrorList
5960+
rmFldPath := fldPath.Child("requestMappings")
5961+
if len(status.RequestMappings) == 0 {
5962+
allErrs = append(allErrs, field.Required(rmFldPath, "at least one request mapping is required"))
5963+
}
5964+
type key struct {
5965+
container string
5966+
resource string
5967+
}
5968+
seen := map[key]struct{}{}
5969+
for i, rm := range status.RequestMappings {
5970+
idxPath := rmFldPath.Index(i)
5971+
c, ok := containers[rm.ContainerName]
5972+
if ok {
5973+
if _, ok := c.Resources.Requests[core.ResourceName(rm.ResourceName)]; !ok {
5974+
allErrs = append(allErrs, field.Invalid(idxPath.Child("resourceName"), rm.ResourceName, "must match the extended resource name of an entry in spec.initContainers.resources.requests or spec.containers.resources.requests"))
5975+
}
5976+
} else {
5977+
allErrs = append(allErrs, field.Invalid(idxPath.Child("containerName"), rm.ContainerName, "must match the name of an entry in spec.initContainers.name or spec.containers.name"))
5978+
}
5979+
allErrs = append(allErrs, ValidateDNS1123Label(rm.RequestName, fldPath.Child("requestName"))...)
5980+
k := key{container: rm.ContainerName, resource: rm.ResourceName}
5981+
if _, ok := seen[k]; ok {
5982+
allErrs = append(allErrs, field.Duplicate(idxPath.Child("containerName"), rm.ContainerName))
5983+
allErrs = append(allErrs, field.Duplicate(idxPath.Child("resourceName"), rm.ResourceName))
5984+
}
5985+
seen[k] = struct{}{}
5986+
}
5987+
if len(status.ResourceClaimName) == 0 {
5988+
allErrs = append(allErrs, field.Required(fldPath.Child("resourceClaimName"), ""))
5989+
} else {
5990+
for _, detail := range ValidateResourceClaimName(status.ResourceClaimName, false) {
5991+
allErrs = append(allErrs, field.Invalid(fldPath.Child("resourceClaimName"), status.ResourceClaimName, detail))
5992+
}
5993+
}
5994+
return allErrs
5995+
}
5996+
59445997
func havePodClaim(podClaims []core.PodResourceClaim, name string) bool {
59455998
for _, podClaim := range podClaims {
59465999
if podClaim.Name == name {

0 commit comments

Comments
 (0)