diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index af14dfac5ed..cbc62a4886f 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -15562,6 +15562,10 @@ "io.k8s.api.resource.v1alpha3.DeviceRequestAllocationResult": { "description": "DeviceRequestAllocationResult contains the allocation result for one request.", "properties": { + "adminAccess": { + "description": "AdminAccess is a copy of the AdminAccess value in the request which caused this device to be allocated.\n\nNew allocations are required to have this set. Old allocations made by Kubernetes 1.31 do not have it yet. Clients which want to support Kubernetes 1.31 need to look up the request and retrieve the value from there if this field is not set.", + "type": "boolean" + }, "device": { "description": "Device references one device instance via its name in the driver's resource pool. It must be a DNS label.", "type": "string" @@ -15583,7 +15587,8 @@ "request", "driver", "pool", - "device" + "device", + "adminAccess" ], "type": "object" }, diff --git a/api/openapi-spec/v3/apis__resource.k8s.io__v1alpha3_openapi.json b/api/openapi-spec/v3/apis__resource.k8s.io__v1alpha3_openapi.json index a65fc3728cd..709f87af1ae 100644 --- a/api/openapi-spec/v3/apis__resource.k8s.io__v1alpha3_openapi.json +++ b/api/openapi-spec/v3/apis__resource.k8s.io__v1alpha3_openapi.json @@ -526,6 +526,10 @@ "io.k8s.api.resource.v1alpha3.DeviceRequestAllocationResult": { "description": "DeviceRequestAllocationResult contains the allocation result for one request.", "properties": { + "adminAccess": { + "description": "AdminAccess is a copy of the AdminAccess value in the request which caused this device to be allocated.\n\nNew allocations are required to have this set. Old allocations made by Kubernetes 1.31 do not have it yet. Clients which want to support Kubernetes 1.31 need to look up the request and retrieve the value from there if this field is not set.", + "type": "boolean" + }, "device": { "default": "", "description": "Device references one device instance via its name in the driver's resource pool. It must be a DNS label.", @@ -551,7 +555,8 @@ "request", "driver", "pool", - "device" + "device", + "adminAccess" ], "type": "object" }, diff --git a/pkg/apis/resource/types.go b/pkg/apis/resource/types.go index 5246bc52528..4124df47bda 100644 --- a/pkg/apis/resource/types.go +++ b/pkg/apis/resource/types.go @@ -782,6 +782,17 @@ type DeviceRequestAllocationResult struct { // // +required Device string + + // AdminAccess is a copy of the AdminAccess value in the + // request which caused this device to be allocated. + // + // New allocations are required to have this set. Old allocations made + // by Kubernetes 1.31 do not have it yet. Clients which want to + // support Kubernetes 1.31 need to look up the request and retrieve + // the value from there if this field is not set. + // + // +required + AdminAccess *bool } // DeviceAllocationConfiguration gets embedded in an AllocationResult. diff --git a/pkg/apis/resource/v1alpha3/zz_generated.conversion.go b/pkg/apis/resource/v1alpha3/zz_generated.conversion.go index a998aac2ac5..cd43bd14793 100644 --- a/pkg/apis/resource/v1alpha3/zz_generated.conversion.go +++ b/pkg/apis/resource/v1alpha3/zz_generated.conversion.go @@ -741,6 +741,7 @@ func autoConvert_v1alpha3_DeviceRequestAllocationResult_To_resource_DeviceReques out.Driver = in.Driver out.Pool = in.Pool out.Device = in.Device + out.AdminAccess = (*bool)(unsafe.Pointer(in.AdminAccess)) return nil } @@ -754,6 +755,7 @@ func autoConvert_resource_DeviceRequestAllocationResult_To_v1alpha3_DeviceReques out.Driver = in.Driver out.Pool = in.Pool out.Device = in.Device + out.AdminAccess = (*bool)(unsafe.Pointer(in.AdminAccess)) return nil } diff --git a/pkg/apis/resource/validation/validation.go b/pkg/apis/resource/validation/validation.go index 48f3bb84809..2ddf511d9fd 100644 --- a/pkg/apis/resource/validation/validation.go +++ b/pkg/apis/resource/validation/validation.go @@ -261,7 +261,6 @@ func validateOpaqueConfiguration(config resource.OpaqueDeviceConfiguration, fldP func validateResourceClaimStatusUpdate(status, oldStatus *resource.ResourceClaimStatus, claimDeleted bool, requestNames sets.Set[string], fldPath *field.Path) field.ErrorList { var allErrs field.ErrorList - allErrs = append(allErrs, validateAllocationResult(status.Allocation, fldPath.Child("allocation"), requestNames)...) allErrs = append(allErrs, validateSet(status.ReservedFor, resource.ResourceClaimReservedForMaxSize, validateResourceClaimUserReference, func(consumer resource.ResourceClaimConsumerReference) (types.UID, string) { return consumer.UID, "uid" }, @@ -285,9 +284,14 @@ func validateResourceClaimStatusUpdate(status, oldStatus *resource.ResourceClaim } } - // Updates to a populated status.Allocation are not allowed + // Updates to a populated status.Allocation are not allowed. + // Unmodified fields don't need to be validated again and, + // in this particular case, must not be validated again because + // validation for new results is tighter than it was before. if oldStatus.Allocation != nil && status.Allocation != nil { allErrs = append(allErrs, apimachineryvalidation.ValidateImmutableField(status.Allocation, oldStatus.Allocation, fldPath.Child("allocation"))...) + } else if status.Allocation != nil { + allErrs = append(allErrs, validateAllocationResult(status.Allocation, fldPath.Child("allocation"), requestNames)...) } return allErrs @@ -307,11 +311,10 @@ func validateResourceClaimUserReference(ref resource.ResourceClaimConsumerRefere return allErrs } +// validateAllocationResult enforces constraints for *new* results, which in at +// least one case (admin access) are more strict than before. Therefore it +// may not be called to re-validate results which were stored earlier. func validateAllocationResult(allocation *resource.AllocationResult, fldPath *field.Path, requestNames sets.Set[string]) field.ErrorList { - if allocation == nil { - return nil - } - var allErrs field.ErrorList allErrs = append(allErrs, validateDeviceAllocationResult(allocation.Devices, fldPath.Child("devices"), requestNames)...) if allocation.NodeSelector != nil { @@ -340,6 +343,9 @@ func validateDeviceRequestAllocationResult(result resource.DeviceRequestAllocati allErrs = append(allErrs, validateDriverName(result.Driver, fldPath.Child("driver"))...) allErrs = append(allErrs, validatePoolName(result.Pool, fldPath.Child("pool"))...) allErrs = append(allErrs, validateDeviceName(result.Device, fldPath.Child("device"))...) + if result.AdminAccess == nil { + allErrs = append(allErrs, field.Required(fldPath.Child("adminAccess"), "")) + } return allErrs } diff --git a/pkg/apis/resource/validation/validation_resourceclaim_test.go b/pkg/apis/resource/validation/validation_resourceclaim_test.go index b24ff849a89..b49c8fcffe8 100644 --- a/pkg/apis/resource/validation/validation_resourceclaim_test.go +++ b/pkg/apis/resource/validation/validation_resourceclaim_test.go @@ -408,14 +408,17 @@ func TestValidateClaimStatusUpdate(t *testing.T) { Allocation: &resource.AllocationResult{ Devices: resource.DeviceAllocationResult{ Results: []resource.DeviceRequestAllocationResult{{ - Request: goodName, - Driver: goodName, - Pool: goodName, - Device: goodName, + Request: goodName, + Driver: goodName, + Pool: goodName, + Device: goodName, + AdminAccess: ptr.To(false), // Required for new allocations. }}, }, }, } + validAllocatedClaimOld := validAllocatedClaim.DeepCopy() + validAllocatedClaimOld.Status.Allocation.Devices.Results[0].AdminAccess = nil // Not required in 1.31. scenarios := map[string]struct { oldClaim *resource.ResourceClaim @@ -439,10 +442,11 @@ func TestValidateClaimStatusUpdate(t *testing.T) { claim.Status.Allocation = &resource.AllocationResult{ Devices: resource.DeviceAllocationResult{ Results: []resource.DeviceRequestAllocationResult{{ - Request: goodName, - Driver: goodName, - Pool: goodName, - Device: goodName, + Request: goodName, + Driver: goodName, + Pool: goodName, + Device: goodName, + AdminAccess: ptr.To(false), }}, }, } @@ -459,10 +463,31 @@ func TestValidateClaimStatusUpdate(t *testing.T) { claim.Status.Allocation = &resource.AllocationResult{ Devices: resource.DeviceAllocationResult{ Results: []resource.DeviceRequestAllocationResult{{ - Request: badName, - Driver: goodName, - Pool: goodName, - Device: goodName, + Request: badName, + Driver: goodName, + Pool: goodName, + Device: goodName, + AdminAccess: ptr.To(false), + }}, + }, + } + return claim + }, + }, + "invalid-add-allocation-missing-admin-access": { + wantFailures: field.ErrorList{ + field.Required(field.NewPath("status", "allocation", "devices", "results").Index(0).Child("adminAccess"), ""), + }, + oldClaim: validClaim, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + claim.Status.Allocation = &resource.AllocationResult{ + Devices: resource.DeviceAllocationResult{ + Results: []resource.DeviceRequestAllocationResult{{ + Request: goodName, + Driver: goodName, + Pool: goodName, + Device: goodName, + AdminAccess: nil, // Intentionally not set. }}, }, } @@ -495,6 +520,20 @@ func TestValidateClaimStatusUpdate(t *testing.T) { return claim }, }, + "add-reservation-old-claim": { + oldClaim: validAllocatedClaimOld, + update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { + for i := 0; i < resource.ResourceClaimReservedForMaxSize; i++ { + claim.Status.ReservedFor = append(claim.Status.ReservedFor, + resource.ResourceClaimConsumerReference{ + Resource: "pods", + Name: fmt.Sprintf("foo-%d", i), + UID: types.UID(fmt.Sprintf("%d", i)), + }) + } + return claim + }, + }, "add-reservation-and-allocation": { oldClaim: validClaim, update: func(claim *resource.ResourceClaim) *resource.ResourceClaim { diff --git a/pkg/apis/resource/zz_generated.deepcopy.go b/pkg/apis/resource/zz_generated.deepcopy.go index 7243a553af6..0e3ec71422d 100644 --- a/pkg/apis/resource/zz_generated.deepcopy.go +++ b/pkg/apis/resource/zz_generated.deepcopy.go @@ -144,7 +144,9 @@ func (in *DeviceAllocationResult) DeepCopyInto(out *DeviceAllocationResult) { if in.Results != nil { in, out := &in.Results, &out.Results *out = make([]DeviceRequestAllocationResult, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.Config != nil { in, out := &in.Config, &out.Config @@ -441,6 +443,11 @@ func (in *DeviceRequest) DeepCopy() *DeviceRequest { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DeviceRequestAllocationResult) DeepCopyInto(out *DeviceRequestAllocationResult) { *out = *in + if in.AdminAccess != nil { + in, out := &in.AdminAccess, &out.AdminAccess + *out = new(bool) + **out = **in + } return } diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 19733195c6e..30dc6683955 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -46558,8 +46558,15 @@ func schema_k8sio_api_resource_v1alpha3_DeviceRequestAllocationResult(ref common Format: "", }, }, + "adminAccess": { + SchemaProps: spec.SchemaProps{ + Description: "AdminAccess is a copy of the AdminAccess value in the request which caused this device to be allocated.\n\nNew allocations are required to have this set. Old allocations made by Kubernetes 1.31 do not have it yet. Clients which want to support Kubernetes 1.31 need to look up the request and retrieve the value from there if this field is not set.", + Type: []string{"boolean"}, + Format: "", + }, + }, }, - Required: []string{"request", "driver", "pool", "device"}, + Required: []string{"request", "driver", "pool", "device", "adminAccess"}, }, }, } diff --git a/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go index 1292f1ac680..e03a93877c4 100644 --- a/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go +++ b/pkg/scheduler/framework/plugins/dynamicresources/dynamicresources_test.go @@ -135,10 +135,11 @@ var ( allocationResult = &resourceapi.AllocationResult{ Devices: resourceapi.DeviceAllocationResult{ Results: []resourceapi.DeviceRequestAllocationResult{{ - Driver: driver, - Pool: nodeName, - Device: "instance-1", - Request: "req-1", + Driver: driver, + Pool: nodeName, + Device: "instance-1", + Request: "req-1", + AdminAccess: ptr.To(false), }}, }, NodeSelector: func() *v1.NodeSelector { @@ -178,6 +179,19 @@ func reserve(claim *resourceapi.ResourceClaim, pod *v1.Pod) *resourceapi.Resourc Obj() } +func adminAccess(claim *resourceapi.ResourceClaim) *resourceapi.ResourceClaim { + claim = claim.DeepCopy() + for i := range claim.Spec.Devices.Requests { + claim.Spec.Devices.Requests[i].AdminAccess = true + } + if claim.Status.Allocation != nil { + for i := range claim.Status.Allocation.Devices.Results { + claim.Status.Allocation.Devices.Results[i].AdminAccess = ptr.To(true) + } + } + return claim +} + func breakCELInClaim(claim *resourceapi.ResourceClaim) *resourceapi.ResourceClaim { claim = claim.DeepCopy() for i := range claim.Spec.Devices.Requests { @@ -556,6 +570,66 @@ func TestPlugin(t *testing.T) { }, }, + "request-admin-access": { + // Because the pending claim asks for admin access, allocation succeeds despite resources + // being exhausted. + pod: podWithClaimName, + claims: []*resourceapi.ResourceClaim{adminAccess(pendingClaim), otherAllocatedClaim}, + classes: []*resourceapi.DeviceClass{deviceClass}, + objs: []apiruntime.Object{workerNodeSlice}, + want: want{ + reserve: result{ + inFlightClaim: adminAccess(allocatedClaim), + }, + prebind: result{ + assumedClaim: reserve(adminAccess(allocatedClaim), podWithClaimName), + changes: change{ + claim: func(claim *resourceapi.ResourceClaim) *resourceapi.ResourceClaim { + if claim.Name == claimName { + claim = claim.DeepCopy() + claim.Finalizers = allocatedClaim.Finalizers + claim.Status = adminAccess(inUseClaim).Status + } + return claim + }, + }, + }, + postbind: result{ + assumedClaim: reserve(adminAccess(allocatedClaim), podWithClaimName), + }, + }, + }, + + "structured-ignore-allocated-admin-access": { + // The allocated claim uses admin access, so a second claim may use + // the same device. + pod: podWithClaimName, + claims: []*resourceapi.ResourceClaim{pendingClaim, adminAccess(otherAllocatedClaim)}, + classes: []*resourceapi.DeviceClass{deviceClass}, + objs: []apiruntime.Object{workerNodeSlice}, + want: want{ + reserve: result{ + inFlightClaim: allocatedClaim, + }, + prebind: result{ + assumedClaim: reserve(allocatedClaim, podWithClaimName), + changes: change{ + claim: func(claim *resourceapi.ResourceClaim) *resourceapi.ResourceClaim { + if claim.Name == claimName { + claim = claim.DeepCopy() + claim.Finalizers = allocatedClaim.Finalizers + claim.Status = inUseClaim.Status + } + return claim + }, + }, + }, + postbind: result{ + assumedClaim: reserve(allocatedClaim, podWithClaimName), + }, + }, + }, + "claim-parameters-CEL-runtime-error": { pod: podWithClaimName, claims: []*resourceapi.ResourceClaim{breakCELInClaim(pendingClaim)}, diff --git a/staging/src/k8s.io/api/resource/v1alpha3/generated.pb.go b/staging/src/k8s.io/api/resource/v1alpha3/generated.pb.go index d60033a89c0..2b2c654c90e 100644 --- a/staging/src/k8s.io/api/resource/v1alpha3/generated.pb.go +++ b/staging/src/k8s.io/api/resource/v1alpha3/generated.pb.go @@ -957,122 +957,122 @@ func init() { } var fileDescriptor_66649ee9bbcd89d2 = []byte{ - // 1832 bytes of a gzipped FileDescriptorProto + // 1840 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x19, 0xcd, 0x6f, 0xe4, 0x56, - 0x3d, 0x1e, 0x27, 0x93, 0xc9, 0x6f, 0xf2, 0xb5, 0x6f, 0xa1, 0x64, 0x43, 0x99, 0xd9, 0x75, 0x11, - 0x64, 0xdb, 0xad, 0xa7, 0xbb, 0x2d, 0x6d, 0xa1, 0x1c, 0x88, 0x93, 0x74, 0x95, 0xd5, 0x7e, 0x64, - 0x5f, 0xda, 0x15, 0x0b, 0xa5, 0xf0, 0xe2, 0x79, 0x99, 0x98, 0x78, 0x6c, 0xd7, 0xef, 0x79, 0x68, - 0x2e, 0xa8, 0xe2, 0xc2, 0x6d, 0xc5, 0x3f, 0x80, 0xb8, 0x21, 0x71, 0x82, 0x3f, 0x00, 0x09, 0x24, - 0x90, 0x58, 0x89, 0xcb, 0x4a, 0x70, 0xe8, 0x69, 0xe8, 0x0e, 0xe2, 0xc2, 0x9f, 0x90, 0x13, 0xf2, - 0xf3, 0xf3, 0xe7, 0x8c, 0xb3, 0x9e, 0xaa, 0x44, 0xed, 0x6d, 0xfc, 0xfb, 0xfe, 0xfe, 0xfd, 0xec, - 0x81, 0x6b, 0xc7, 0x6f, 0x32, 0xdd, 0x72, 0x3b, 0xc4, 0xb3, 0x3a, 0x3e, 0x65, 0x6e, 0xe0, 0x9b, - 0xb4, 0x33, 0xb8, 0x4e, 0x6c, 0xef, 0x88, 0xbc, 0xda, 0xe9, 0x51, 0x87, 0xfa, 0x84, 0xd3, 0xae, - 0xee, 0xf9, 0x2e, 0x77, 0xd1, 0xf3, 0x11, 0xb5, 0x4e, 0x3c, 0x4b, 0x8f, 0xa9, 0xf5, 0x98, 0x7a, - 0xfd, 0xe5, 0x9e, 0xc5, 0x8f, 0x82, 0x03, 0xdd, 0x74, 0xfb, 0x9d, 0x9e, 0xdb, 0x73, 0x3b, 0x82, - 0xe9, 0x20, 0x38, 0x14, 0x4f, 0xe2, 0x41, 0xfc, 0x8a, 0x84, 0xad, 0x6b, 0x19, 0xd5, 0xa6, 0xeb, - 0x87, 0x6a, 0x8b, 0x0a, 0xd7, 0x5f, 0x4b, 0x69, 0xfa, 0xc4, 0x3c, 0xb2, 0x1c, 0xea, 0x9f, 0x74, - 0xbc, 0xe3, 0x5e, 0xde, 0xde, 0x69, 0xb8, 0x58, 0xa7, 0x4f, 0x39, 0x99, 0xa4, 0xab, 0x53, 0xc6, - 0xe5, 0x07, 0x0e, 0xb7, 0xfa, 0xe3, 0x6a, 0x5e, 0x7f, 0x16, 0x03, 0x33, 0x8f, 0x68, 0x9f, 0x14, - 0xf9, 0xb4, 0xbf, 0x2b, 0xb0, 0xba, 0x69, 0xdb, 0xae, 0x49, 0xb8, 0xe5, 0x3a, 0x98, 0xb2, 0xc0, - 0xe6, 0xe8, 0xc7, 0x30, 0xdf, 0xa5, 0x03, 0xcb, 0xa4, 0x6c, 0x4d, 0xb9, 0xac, 0x6c, 0x34, 0x6f, - 0xbc, 0xa6, 0x9f, 0x15, 0x6c, 0x7d, 0x5b, 0x10, 0x17, 0xc5, 0x18, 0x2b, 0x8f, 0x87, 0xed, 0x99, - 0xd1, 0xb0, 0x3d, 0x1f, 0xe1, 0x19, 0x8e, 0xa5, 0xa2, 0x07, 0xb0, 0xe8, 0xb8, 0x5d, 0xba, 0x4f, - 0x6d, 0x6a, 0x72, 0xd7, 0x5f, 0x53, 0x85, 0x96, 0xcb, 0x59, 0x2d, 0x61, 0x16, 0xf4, 0xc1, 0x75, - 0xfd, 0x6e, 0x86, 0xce, 0x58, 0x1d, 0x0d, 0xdb, 0x8b, 0x59, 0x08, 0xce, 0xc9, 0xd1, 0x3e, 0x51, - 0xa1, 0x69, 0x10, 0x66, 0x99, 0x91, 0x46, 0xf4, 0x73, 0x00, 0xc2, 0xb9, 0x6f, 0x1d, 0x04, 0x5c, - 0xf8, 0xa2, 0x6e, 0x34, 0x6f, 0x7c, 0xfb, 0x6c, 0x5f, 0x32, 0xec, 0xfa, 0x66, 0xc2, 0xbb, 0xe3, - 0x70, 0xff, 0xc4, 0x78, 0x41, 0x3a, 0x04, 0x29, 0xe2, 0x17, 0xff, 0x6a, 0x2f, 0xdd, 0x0f, 0x88, - 0x6d, 0x1d, 0x5a, 0xb4, 0x7b, 0x97, 0xf4, 0x29, 0xce, 0x68, 0x44, 0x03, 0x68, 0x98, 0xc4, 0x23, - 0xa6, 0xc5, 0x4f, 0xd6, 0x6a, 0x42, 0xfb, 0x1b, 0xd5, 0xb5, 0x6f, 0x49, 0xce, 0x48, 0xf7, 0x15, - 0xa9, 0xbb, 0x11, 0x83, 0xc7, 0x35, 0x27, 0xba, 0xd6, 0x6d, 0x58, 0x29, 0xd8, 0x8e, 0x56, 0x41, - 0x3d, 0xa6, 0x27, 0x22, 0x9f, 0x0b, 0x38, 0xfc, 0x89, 0xb6, 0x60, 0x6e, 0x40, 0xec, 0x80, 0xae, - 0xd5, 0x44, 0xf4, 0x5f, 0xae, 0x94, 0xe3, 0x58, 0x2a, 0x8e, 0x78, 0xbf, 0x53, 0x7b, 0x53, 0x59, - 0x3f, 0x86, 0xa5, 0x9c, 0xad, 0x13, 0x74, 0x6d, 0xe7, 0x75, 0xe9, 0x19, 0x5d, 0x49, 0xb9, 0xea, - 0xde, 0x71, 0x2f, 0xaf, 0xfc, 0x7e, 0x40, 0x1c, 0x6e, 0xf1, 0x93, 0x8c, 0x32, 0xed, 0x26, 0x5c, - 0xd8, 0xda, 0xb9, 0x1d, 0x59, 0x13, 0xe7, 0x1d, 0xdd, 0x00, 0xa0, 0x1f, 0x7a, 0x3e, 0x65, 0xcc, - 0x72, 0x9d, 0x48, 0xaf, 0x81, 0xe2, 0x64, 0xed, 0x24, 0x18, 0x9c, 0xa1, 0xd2, 0x06, 0x50, 0x97, - 0x55, 0x72, 0x19, 0x66, 0x1d, 0xd2, 0xa7, 0x92, 0x6f, 0x51, 0xf2, 0xcd, 0x8a, 0x98, 0x0a, 0x0c, - 0xba, 0x05, 0x73, 0x07, 0x61, 0x66, 0xa4, 0xf9, 0x57, 0x2b, 0x27, 0xd1, 0x58, 0x18, 0x0d, 0xdb, - 0x73, 0x02, 0x80, 0x23, 0x11, 0xda, 0xa3, 0x1a, 0x7c, 0xad, 0xd8, 0x30, 0x5b, 0xae, 0x73, 0x68, - 0xf5, 0x02, 0x5f, 0x3c, 0xa0, 0xef, 0x41, 0x3d, 0x12, 0x29, 0x2d, 0xda, 0x90, 0x16, 0xd5, 0xf7, - 0x05, 0xf4, 0x74, 0xd8, 0x7e, 0xae, 0xc8, 0x1a, 0x61, 0xb0, 0xe4, 0x43, 0x1b, 0xd0, 0xf0, 0xe9, - 0x07, 0x01, 0x65, 0x9c, 0x89, 0xba, 0x5b, 0x30, 0x16, 0xc3, 0xd2, 0xc1, 0x12, 0x86, 0x13, 0x2c, - 0xfa, 0x48, 0x81, 0x8b, 0x51, 0x57, 0xe6, 0x6c, 0x90, 0x1d, 0x79, 0xbd, 0x4a, 0x4d, 0xe4, 0x18, - 0x8d, 0xaf, 0x4a, 0x63, 0x2f, 0x4e, 0x40, 0xe2, 0x49, 0xaa, 0xb4, 0xff, 0x28, 0xf0, 0xdc, 0xe4, - 0x09, 0x82, 0x0e, 0x61, 0xde, 0x17, 0xbf, 0xe2, 0xe6, 0x7d, 0xab, 0x8a, 0x41, 0xd2, 0xcd, 0xf2, - 0x79, 0x14, 0x3d, 0x33, 0x1c, 0x0b, 0x47, 0x26, 0xd4, 0x4d, 0x61, 0x93, 0xec, 0xd2, 0xb7, 0xa6, - 0x9b, 0x77, 0xf9, 0x08, 0x2c, 0xc7, 0xe9, 0x8a, 0xc0, 0x58, 0x8a, 0xd6, 0x7e, 0xa7, 0xc0, 0x4a, - 0xa1, 0x8b, 0x50, 0x0b, 0x54, 0xcb, 0xe1, 0xa2, 0xac, 0xd4, 0x28, 0x47, 0xbb, 0x0e, 0x7f, 0x10, - 0x16, 0x3b, 0x0e, 0x11, 0xe8, 0x0a, 0xcc, 0x1e, 0xb8, 0xae, 0x2d, 0xd2, 0xd1, 0x30, 0x96, 0x46, - 0xc3, 0xf6, 0x82, 0xe1, 0xba, 0x76, 0x44, 0x21, 0x50, 0xe8, 0x9b, 0x50, 0x67, 0xdc, 0xb7, 0x9c, - 0xde, 0xda, 0xac, 0xa8, 0x96, 0x95, 0xd1, 0xb0, 0xdd, 0xdc, 0x17, 0x90, 0x88, 0x4c, 0xa2, 0xd1, - 0x8b, 0x30, 0x3f, 0xa0, 0xbe, 0xe8, 0x90, 0x39, 0x41, 0x29, 0xa6, 0xe9, 0x83, 0x08, 0x14, 0x91, - 0xc6, 0x04, 0xda, 0xef, 0x6b, 0xd0, 0x94, 0x09, 0xb4, 0x89, 0xd5, 0x47, 0x0f, 0x33, 0x05, 0x15, - 0x65, 0xe2, 0xa5, 0x29, 0x32, 0x61, 0xac, 0xc6, 0xc3, 0x6b, 0x42, 0x05, 0x52, 0x68, 0x9a, 0xae, - 0xc3, 0xb8, 0x4f, 0x2c, 0x47, 0x96, 0x6b, 0x7e, 0x40, 0x9c, 0x55, 0x78, 0x92, 0xcd, 0xb8, 0x28, - 0x15, 0x34, 0x53, 0x18, 0xc3, 0x59, 0xb9, 0xe8, 0xfd, 0x24, 0xc5, 0xaa, 0xd0, 0xf0, 0x7a, 0x25, - 0x0d, 0xa1, 0xf3, 0xd5, 0xb2, 0xfb, 0x37, 0x05, 0xd6, 0xca, 0x98, 0x72, 0xfd, 0xa8, 0x7c, 0xaa, - 0x7e, 0xac, 0x9d, 0x5f, 0x3f, 0xfe, 0x59, 0xc9, 0xe4, 0x9e, 0x31, 0xf4, 0x13, 0x68, 0x84, 0x67, - 0x4a, 0x97, 0x70, 0x22, 0xcf, 0x81, 0x57, 0xce, 0x1a, 0xdf, 0x4c, 0x0f, 0xa9, 0xc3, 0xd5, 0x7d, - 0xef, 0xe0, 0xa7, 0xd4, 0xe4, 0x77, 0x28, 0x27, 0xe9, 0x30, 0x4e, 0x61, 0x38, 0x91, 0x8a, 0xee, - 0xc1, 0x2c, 0xf3, 0xa8, 0x39, 0xcd, 0x22, 0x12, 0xa6, 0xed, 0x7b, 0xd4, 0x4c, 0xe7, 0x75, 0xf8, - 0x84, 0x85, 0x20, 0xed, 0xd7, 0xd9, 0x64, 0x30, 0x96, 0x4f, 0x46, 0x59, 0x88, 0x95, 0xf3, 0x0b, - 0xf1, 0x9f, 0x92, 0x51, 0x20, 0xec, 0xbb, 0x6d, 0x31, 0x8e, 0xde, 0x1b, 0x0b, 0xb3, 0x5e, 0x2d, - 0xcc, 0x21, 0xb7, 0x08, 0x72, 0xd2, 0x65, 0x31, 0x24, 0x13, 0xe2, 0xbb, 0x30, 0x67, 0x71, 0xda, - 0x8f, 0xfb, 0xeb, 0x6a, 0xe5, 0x18, 0x1b, 0x4b, 0x52, 0xea, 0xdc, 0x6e, 0xc8, 0x8f, 0x23, 0x31, - 0xda, 0x93, 0xbc, 0x07, 0x61, 0xec, 0xd1, 0x8f, 0x60, 0x81, 0xc9, 0x8d, 0x1c, 0x4f, 0x89, 0x6b, - 0x55, 0xf4, 0x24, 0xe7, 0xdd, 0x05, 0xa9, 0x6a, 0x21, 0x86, 0x30, 0x9c, 0x4a, 0xcc, 0x74, 0x70, - 0x6d, 0xaa, 0x0e, 0x2e, 0xe4, 0xbf, 0xb4, 0x83, 0x7d, 0x98, 0x94, 0x40, 0xf4, 0x43, 0xa8, 0xbb, - 0x1e, 0xf9, 0x20, 0xa0, 0x32, 0x2b, 0xcf, 0xb8, 0xe0, 0xee, 0x09, 0xda, 0x49, 0x65, 0x02, 0xa1, - 0xce, 0x08, 0x8d, 0xa5, 0x48, 0xed, 0x91, 0x02, 0xab, 0xc5, 0x61, 0x36, 0xc5, 0xb4, 0xd8, 0x83, - 0xe5, 0x3e, 0xe1, 0xe6, 0x51, 0xb2, 0x50, 0x44, 0x0b, 0x2d, 0x18, 0x1b, 0xa3, 0x61, 0x7b, 0xf9, - 0x4e, 0x0e, 0x73, 0x3a, 0x6c, 0xa3, 0xb7, 0x03, 0xdb, 0x3e, 0xc9, 0xdf, 0x8c, 0x05, 0x7e, 0xed, - 0x97, 0x2a, 0x2c, 0xe5, 0x66, 0x77, 0x85, 0xeb, 0x68, 0x13, 0x56, 0xba, 0x69, 0xb0, 0x43, 0x84, - 0x34, 0xe3, 0x2b, 0x92, 0x38, 0x5b, 0x29, 0x82, 0xaf, 0x48, 0x9f, 0x2f, 0x1d, 0xf5, 0x33, 0x2f, - 0x9d, 0x07, 0xb0, 0x4c, 0x92, 0x6d, 0x7d, 0xc7, 0xed, 0x52, 0xb9, 0x2b, 0x75, 0xc9, 0xb5, 0xbc, - 0x99, 0xc3, 0x9e, 0x0e, 0xdb, 0x5f, 0x2a, 0xee, 0xf8, 0x10, 0x8e, 0x0b, 0x52, 0xd0, 0x0b, 0x30, - 0x67, 0xba, 0x81, 0xc3, 0xc5, 0x42, 0x55, 0xd3, 0x56, 0xd9, 0x0a, 0x81, 0x38, 0xc2, 0xa1, 0x6f, - 0x41, 0x93, 0x74, 0xfb, 0x96, 0xb3, 0x69, 0x9a, 0x94, 0xb1, 0xb5, 0xba, 0x58, 0xe5, 0xc9, 0xc2, - 0xda, 0x4c, 0x51, 0x38, 0x4b, 0xa7, 0xfd, 0x51, 0x89, 0xef, 0xc4, 0x92, 0x7b, 0x06, 0x5d, 0x0d, - 0xaf, 0x23, 0x81, 0x92, 0xc9, 0xc9, 0x1c, 0x38, 0x02, 0x8c, 0x63, 0x3c, 0xfa, 0x06, 0xd4, 0xbb, - 0xbe, 0x35, 0xa0, 0xbe, 0xcc, 0x4c, 0xd2, 0x03, 0xdb, 0x02, 0x8a, 0x25, 0x36, 0x4c, 0xb6, 0x17, - 0xdf, 0x1b, 0x99, 0x64, 0xef, 0xb9, 0xae, 0x8d, 0x05, 0x46, 0x48, 0x12, 0x56, 0xc9, 0x10, 0xa6, - 0x92, 0x22, 0x5b, 0x25, 0x56, 0x7b, 0x0f, 0x96, 0x0b, 0x47, 0xfa, 0x2d, 0x50, 0x4d, 0x6a, 0xcb, - 0x2e, 0xea, 0x9c, 0x9d, 0xdd, 0xb1, 0x13, 0xdf, 0x98, 0x1f, 0x0d, 0xdb, 0xea, 0xd6, 0xce, 0x6d, - 0x1c, 0x0a, 0xd1, 0x7e, 0xab, 0xc0, 0xa5, 0xd2, 0x4e, 0xcb, 0x78, 0xab, 0x9c, 0xe9, 0x2d, 0x01, - 0xf0, 0x88, 0x4f, 0xfa, 0x94, 0x53, 0x9f, 0x4d, 0xd8, 0x3e, 0xf9, 0xa1, 0x2b, 0xdf, 0xa4, 0x75, - 0x4c, 0x7e, 0xb6, 0xf3, 0x21, 0xa7, 0x4e, 0x78, 0x28, 0xa5, 0x8b, 0x6d, 0x2f, 0x11, 0x84, 0x33, - 0x42, 0xb5, 0xdf, 0xd4, 0x60, 0x09, 0x4b, 0xf7, 0xa2, 0x53, 0xea, 0xff, 0xbf, 0x4e, 0xef, 0xe7, - 0xd6, 0xe9, 0x33, 0x22, 0x9d, 0x33, 0xae, 0x6c, 0xa1, 0xa2, 0x87, 0xe1, 0x91, 0x49, 0x78, 0xc0, - 0xaa, 0xbd, 0x18, 0xe4, 0x85, 0x0a, 0xc6, 0x34, 0x09, 0xd1, 0x33, 0x96, 0x02, 0xb5, 0x91, 0x02, - 0xad, 0x1c, 0x7d, 0x38, 0x09, 0x83, 0x3e, 0xf5, 0x31, 0x3d, 0xa4, 0x3e, 0x75, 0x4c, 0x8a, 0xae, - 0x41, 0x83, 0x78, 0xd6, 0x4d, 0xdf, 0x0d, 0x3c, 0x99, 0xd1, 0x64, 0xd5, 0x6d, 0xee, 0xed, 0x0a, - 0x38, 0x4e, 0x28, 0x42, 0xea, 0xd8, 0x22, 0x59, 0xc7, 0x99, 0xf3, 0x33, 0x82, 0xe3, 0x84, 0x22, - 0x19, 0x6f, 0xb3, 0xa5, 0xe3, 0xcd, 0x00, 0x35, 0xb0, 0xba, 0xf2, 0x66, 0x7e, 0x45, 0x12, 0xa8, - 0xef, 0xee, 0x6e, 0x9f, 0x0e, 0xdb, 0x57, 0xca, 0x3e, 0xbb, 0xf0, 0x13, 0x8f, 0x32, 0xfd, 0xdd, - 0xdd, 0x6d, 0x1c, 0x32, 0x6b, 0x7f, 0x51, 0xe0, 0x42, 0xce, 0xc9, 0x73, 0x58, 0xf9, 0x7b, 0xf9, - 0x95, 0xff, 0xd2, 0x14, 0x29, 0x2b, 0x59, 0xfa, 0x56, 0xc1, 0x09, 0xb1, 0xf5, 0xdf, 0x29, 0x7e, - 0x2c, 0xba, 0x5a, 0xf9, 0xb2, 0x2e, 0xff, 0x42, 0xa4, 0xfd, 0x57, 0x81, 0x8b, 0x13, 0xaa, 0x08, - 0xbd, 0x0f, 0x90, 0xce, 0xe0, 0x09, 0x41, 0x9b, 0xa0, 0x70, 0xec, 0x3d, 0x70, 0x59, 0x7c, 0xc2, - 0x49, 0xa1, 0x19, 0x89, 0x88, 0x41, 0xd3, 0xa7, 0x8c, 0xfa, 0x03, 0xda, 0x7d, 0xdb, 0xf5, 0x65, - 0xe8, 0xbe, 0x3b, 0x45, 0xe8, 0xc6, 0xaa, 0x37, 0x1d, 0xf5, 0x38, 0x15, 0x8c, 0xb3, 0x5a, 0xb4, - 0x7f, 0x2a, 0xf0, 0xe5, 0x9c, 0x90, 0x77, 0x68, 0xdf, 0xb3, 0x09, 0xa7, 0xe7, 0x30, 0x2c, 0x1e, - 0xe6, 0x86, 0xc5, 0x1b, 0x53, 0x78, 0x1a, 0x1b, 0x59, 0x7a, 0x85, 0xff, 0x43, 0x81, 0x4b, 0x13, - 0x39, 0xce, 0xa1, 0xf8, 0xbf, 0x9f, 0x2f, 0xfe, 0x57, 0x3f, 0x85, 0x5f, 0xe5, 0x97, 0xef, 0xa5, - 0xd2, 0x38, 0x7c, 0x21, 0xa7, 0xbb, 0xf6, 0x07, 0x05, 0x16, 0x63, 0xca, 0x70, 0xd5, 0x57, 0xb8, - 0xf9, 0x6e, 0x00, 0xc8, 0x4f, 0xc9, 0xf1, 0xdb, 0xa9, 0x9a, 0xda, 0x7d, 0x33, 0xc1, 0xe0, 0x0c, - 0x15, 0xba, 0x05, 0x28, 0xb6, 0x70, 0xdf, 0x16, 0x4b, 0x3b, 0x3c, 0x9d, 0x54, 0xc1, 0xbb, 0x2e, - 0x79, 0x11, 0x1e, 0xa3, 0xc0, 0x13, 0xb8, 0xb4, 0xbf, 0x2a, 0xe9, 0x5e, 0x15, 0xe0, 0xcf, 0x6b, - 0xe4, 0x85, 0x71, 0xa5, 0x91, 0xcf, 0xee, 0x05, 0x41, 0xf9, 0xb9, 0xdd, 0x0b, 0xc2, 0xba, 0x92, - 0x96, 0x78, 0xa4, 0x16, 0xbc, 0x10, 0xad, 0x50, 0xf5, 0x0a, 0xbb, 0x2d, 0x6f, 0xce, 0x28, 0xac, - 0x2f, 0x56, 0x33, 0x27, 0x2c, 0xd3, 0x89, 0xf7, 0xe9, 0x35, 0x68, 0x38, 0x6e, 0x97, 0x8a, 0xb7, - 0x90, 0xc2, 0xf6, 0xbf, 0x2b, 0xe1, 0x38, 0xa1, 0x18, 0xfb, 0x23, 0x62, 0xf6, 0xb3, 0xf9, 0x23, - 0x42, 0x5c, 0x2c, 0xb6, 0x1d, 0x12, 0x30, 0x71, 0x38, 0x34, 0x32, 0x17, 0x8b, 0x84, 0xe3, 0x84, - 0x02, 0xdd, 0x4b, 0x57, 0x68, 0x5d, 0xe4, 0xe4, 0xeb, 0x55, 0x56, 0x68, 0xf9, 0xf6, 0x34, 0x8c, - 0xc7, 0x4f, 0x5b, 0x33, 0x4f, 0x9e, 0xb6, 0x66, 0x3e, 0x7e, 0xda, 0x9a, 0xf9, 0x68, 0xd4, 0x52, - 0x1e, 0x8f, 0x5a, 0xca, 0x93, 0x51, 0x4b, 0xf9, 0x78, 0xd4, 0x52, 0x3e, 0x19, 0xb5, 0x94, 0x5f, - 0xfd, 0xbb, 0x35, 0xf3, 0x83, 0xe7, 0xcf, 0xfa, 0xbf, 0xed, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, - 0xaa, 0x59, 0xd2, 0xe3, 0x8e, 0x1b, 0x00, 0x00, + 0x3d, 0x8e, 0x33, 0x93, 0xe4, 0x37, 0xf9, 0xda, 0xb7, 0x50, 0xb2, 0xa1, 0xcc, 0xec, 0xba, 0x08, + 0xb2, 0xed, 0xd6, 0xd3, 0xdd, 0x96, 0xb6, 0x50, 0x0e, 0xc4, 0x49, 0xba, 0xca, 0x6a, 0x3f, 0xb2, + 0x2f, 0xed, 0x8a, 0x85, 0x52, 0x78, 0xf1, 0xbc, 0x4c, 0x4c, 0x3c, 0xb6, 0xeb, 0xf7, 0x3c, 0x34, + 0x17, 0x54, 0x71, 0xe1, 0xb6, 0xe2, 0x1f, 0x40, 0xdc, 0x90, 0x38, 0xc1, 0x7f, 0x00, 0x12, 0x48, + 0xac, 0xc4, 0x65, 0x25, 0x38, 0xf4, 0x34, 0x74, 0x07, 0x71, 0xe1, 0xc2, 0x3d, 0x27, 0xe4, 0xe7, + 0xe7, 0xcf, 0x19, 0xcf, 0x7a, 0xaa, 0x12, 0xb5, 0xb7, 0xf1, 0xef, 0xfb, 0xfb, 0xf7, 0xb3, 0x07, + 0xae, 0x9d, 0xbc, 0xc9, 0x74, 0xcb, 0x6d, 0x13, 0xcf, 0x6a, 0xfb, 0x94, 0xb9, 0x81, 0x6f, 0xd2, + 0x76, 0xff, 0x3a, 0xb1, 0xbd, 0x63, 0xf2, 0x6a, 0xbb, 0x4b, 0x1d, 0xea, 0x13, 0x4e, 0x3b, 0xba, + 0xe7, 0xbb, 0xdc, 0x45, 0xcf, 0x47, 0xd4, 0x3a, 0xf1, 0x2c, 0x3d, 0xa6, 0xd6, 0x63, 0xea, 0x8d, + 0x97, 0xbb, 0x16, 0x3f, 0x0e, 0x0e, 0x75, 0xd3, 0xed, 0xb5, 0xbb, 0x6e, 0xd7, 0x6d, 0x0b, 0xa6, + 0xc3, 0xe0, 0x48, 0x3c, 0x89, 0x07, 0xf1, 0x2b, 0x12, 0xb6, 0xa1, 0x65, 0x54, 0x9b, 0xae, 0x1f, + 0xaa, 0x2d, 0x2a, 0xdc, 0x78, 0x2d, 0xa5, 0xe9, 0x11, 0xf3, 0xd8, 0x72, 0xa8, 0x7f, 0xda, 0xf6, + 0x4e, 0xba, 0x79, 0x7b, 0xa7, 0xe1, 0x62, 0xed, 0x1e, 0xe5, 0x64, 0x9c, 0xae, 0x76, 0x19, 0x97, + 0x1f, 0x38, 0xdc, 0xea, 0x8d, 0xaa, 0x79, 0xfd, 0x59, 0x0c, 0xcc, 0x3c, 0xa6, 0x3d, 0x52, 0xe4, + 0xd3, 0xfe, 0xa6, 0xc0, 0xda, 0x96, 0x6d, 0xbb, 0x26, 0xe1, 0x96, 0xeb, 0x60, 0xca, 0x02, 0x9b, + 0xa3, 0x1f, 0xc3, 0x7c, 0x87, 0xf6, 0x2d, 0x93, 0xb2, 0x75, 0xe5, 0xb2, 0xb2, 0xd9, 0xb8, 0xf1, + 0x9a, 0x3e, 0x29, 0xd8, 0xfa, 0x8e, 0x20, 0x2e, 0x8a, 0x31, 0x56, 0x1f, 0x0f, 0x5a, 0x33, 0xc3, + 0x41, 0x6b, 0x3e, 0xc2, 0x33, 0x1c, 0x4b, 0x45, 0x0f, 0x60, 0xc9, 0x71, 0x3b, 0xf4, 0x80, 0xda, + 0xd4, 0xe4, 0xae, 0xbf, 0xae, 0x0a, 0x2d, 0x97, 0xb3, 0x5a, 0xc2, 0x2c, 0xe8, 0xfd, 0xeb, 0xfa, + 0xdd, 0x0c, 0x9d, 0xb1, 0x36, 0x1c, 0xb4, 0x96, 0xb2, 0x10, 0x9c, 0x93, 0xa3, 0x7d, 0xa2, 0x42, + 0xc3, 0x20, 0xcc, 0x32, 0x23, 0x8d, 0xe8, 0xe7, 0x00, 0x84, 0x73, 0xdf, 0x3a, 0x0c, 0xb8, 0xf0, + 0x45, 0xdd, 0x6c, 0xdc, 0xf8, 0xf6, 0x64, 0x5f, 0x32, 0xec, 0xfa, 0x56, 0xc2, 0xbb, 0xeb, 0x70, + 0xff, 0xd4, 0x78, 0x41, 0x3a, 0x04, 0x29, 0xe2, 0x17, 0xff, 0x6c, 0x2d, 0xdf, 0x0f, 0x88, 0x6d, + 0x1d, 0x59, 0xb4, 0x73, 0x97, 0xf4, 0x28, 0xce, 0x68, 0x44, 0x7d, 0x58, 0x30, 0x89, 0x47, 0x4c, + 0x8b, 0x9f, 0xae, 0xcf, 0x0a, 0xed, 0x6f, 0x54, 0xd7, 0xbe, 0x2d, 0x39, 0x23, 0xdd, 0x57, 0xa4, + 0xee, 0x85, 0x18, 0x3c, 0xaa, 0x39, 0xd1, 0xb5, 0x61, 0xc3, 0x6a, 0xc1, 0x76, 0xb4, 0x06, 0xea, + 0x09, 0x3d, 0x15, 0xf9, 0x5c, 0xc4, 0xe1, 0x4f, 0xb4, 0x0d, 0xb5, 0x3e, 0xb1, 0x03, 0xba, 0x3e, + 0x2b, 0xa2, 0xff, 0x72, 0xa5, 0x1c, 0xc7, 0x52, 0x71, 0xc4, 0xfb, 0x9d, 0xd9, 0x37, 0x95, 0x8d, + 0x13, 0x58, 0xce, 0xd9, 0x3a, 0x46, 0xd7, 0x4e, 0x5e, 0x97, 0x9e, 0xd1, 0x95, 0x94, 0xab, 0xee, + 0x9d, 0x74, 0xf3, 0xca, 0xef, 0x07, 0xc4, 0xe1, 0x16, 0x3f, 0xcd, 0x28, 0xd3, 0x6e, 0xc2, 0x85, + 0xed, 0xdd, 0xdb, 0x91, 0x35, 0x71, 0xde, 0xd1, 0x0d, 0x00, 0xfa, 0xa1, 0xe7, 0x53, 0xc6, 0x2c, + 0xd7, 0x89, 0xf4, 0x1a, 0x28, 0x4e, 0xd6, 0x6e, 0x82, 0xc1, 0x19, 0x2a, 0xad, 0x0f, 0x75, 0x59, + 0x25, 0x97, 0x61, 0xce, 0x21, 0x3d, 0x2a, 0xf9, 0x96, 0x24, 0xdf, 0x9c, 0x88, 0xa9, 0xc0, 0xa0, + 0x5b, 0x50, 0x3b, 0x0c, 0x33, 0x23, 0xcd, 0xbf, 0x5a, 0x39, 0x89, 0xc6, 0xe2, 0x70, 0xd0, 0xaa, + 0x09, 0x00, 0x8e, 0x44, 0x68, 0x8f, 0x66, 0xe1, 0x6b, 0xc5, 0x86, 0xd9, 0x76, 0x9d, 0x23, 0xab, + 0x1b, 0xf8, 0xe2, 0x01, 0x7d, 0x0f, 0xea, 0x91, 0x48, 0x69, 0xd1, 0xa6, 0xb4, 0xa8, 0x7e, 0x20, + 0xa0, 0x67, 0x83, 0xd6, 0x73, 0x45, 0xd6, 0x08, 0x83, 0x25, 0x1f, 0xda, 0x84, 0x05, 0x9f, 0x7e, + 0x10, 0x50, 0xc6, 0x99, 0xa8, 0xbb, 0x45, 0x63, 0x29, 0x2c, 0x1d, 0x2c, 0x61, 0x38, 0xc1, 0xa2, + 0x8f, 0x14, 0xb8, 0x18, 0x75, 0x65, 0xce, 0x06, 0xd9, 0x91, 0xd7, 0xab, 0xd4, 0x44, 0x8e, 0xd1, + 0xf8, 0xaa, 0x34, 0xf6, 0xe2, 0x18, 0x24, 0x1e, 0xa7, 0x4a, 0xfb, 0xb7, 0x02, 0xcf, 0x8d, 0x9f, + 0x20, 0xe8, 0x08, 0xe6, 0x7d, 0xf1, 0x2b, 0x6e, 0xde, 0xb7, 0xaa, 0x18, 0x24, 0xdd, 0x2c, 0x9f, + 0x47, 0xd1, 0x33, 0xc3, 0xb1, 0x70, 0x64, 0x42, 0xdd, 0x14, 0x36, 0xc9, 0x2e, 0x7d, 0x6b, 0xba, + 0x79, 0x97, 0x8f, 0xc0, 0x4a, 0x9c, 0xae, 0x08, 0x8c, 0xa5, 0x68, 0xed, 0x77, 0x0a, 0xac, 0x16, + 0xba, 0x08, 0x35, 0x41, 0xb5, 0x1c, 0x2e, 0xca, 0x4a, 0x8d, 0x72, 0xb4, 0xe7, 0xf0, 0x07, 0x61, + 0xb1, 0xe3, 0x10, 0x81, 0xae, 0xc0, 0xdc, 0xa1, 0xeb, 0xda, 0x22, 0x1d, 0x0b, 0xc6, 0xf2, 0x70, + 0xd0, 0x5a, 0x34, 0x5c, 0xd7, 0x8e, 0x28, 0x04, 0x0a, 0x7d, 0x13, 0xea, 0x8c, 0xfb, 0x96, 0xd3, + 0x5d, 0x9f, 0x13, 0xd5, 0xb2, 0x3a, 0x1c, 0xb4, 0x1a, 0x07, 0x02, 0x12, 0x91, 0x49, 0x34, 0x7a, + 0x11, 0xe6, 0xfb, 0xd4, 0x17, 0x1d, 0x52, 0x13, 0x94, 0x62, 0x9a, 0x3e, 0x88, 0x40, 0x11, 0x69, + 0x4c, 0xa0, 0xfd, 0x7e, 0x16, 0x1a, 0x32, 0x81, 0x36, 0xb1, 0x7a, 0xe8, 0x61, 0xa6, 0xa0, 0xa2, + 0x4c, 0xbc, 0x34, 0x45, 0x26, 0x8c, 0xb5, 0x78, 0x78, 0x8d, 0xa9, 0x40, 0x0a, 0x0d, 0xd3, 0x75, + 0x18, 0xf7, 0x89, 0xe5, 0xc8, 0x72, 0xcd, 0x0f, 0x88, 0x49, 0x85, 0x27, 0xd9, 0x8c, 0x8b, 0x52, + 0x41, 0x23, 0x85, 0x31, 0x9c, 0x95, 0x8b, 0xde, 0x4f, 0x52, 0xac, 0x0a, 0x0d, 0xaf, 0x57, 0xd2, + 0x10, 0x3a, 0x5f, 0x2d, 0xbb, 0x7f, 0x55, 0x60, 0xbd, 0x8c, 0x29, 0xd7, 0x8f, 0xca, 0xa7, 0xea, + 0xc7, 0xd9, 0xf3, 0xeb, 0xc7, 0x3f, 0x29, 0x99, 0xdc, 0x33, 0x86, 0x7e, 0x02, 0x0b, 0xe1, 0x99, + 0xd2, 0x21, 0x9c, 0xc8, 0x73, 0xe0, 0x95, 0x49, 0xe3, 0x9b, 0xe9, 0x21, 0x75, 0xb8, 0xba, 0xef, + 0x1d, 0xfe, 0x94, 0x9a, 0xfc, 0x0e, 0xe5, 0x24, 0x1d, 0xc6, 0x29, 0x0c, 0x27, 0x52, 0xd1, 0x3d, + 0x98, 0x63, 0x1e, 0x35, 0xa7, 0x59, 0x44, 0xc2, 0xb4, 0x03, 0x8f, 0x9a, 0xe9, 0xbc, 0x0e, 0x9f, + 0xb0, 0x10, 0xa4, 0xfd, 0x3a, 0x9b, 0x0c, 0xc6, 0xf2, 0xc9, 0x28, 0x0b, 0xb1, 0x72, 0x7e, 0x21, + 0xfe, 0x63, 0x32, 0x0a, 0x84, 0x7d, 0xb7, 0x2d, 0xc6, 0xd1, 0x7b, 0x23, 0x61, 0xd6, 0xab, 0x85, + 0x39, 0xe4, 0x16, 0x41, 0x4e, 0xba, 0x2c, 0x86, 0x64, 0x42, 0x7c, 0x17, 0x6a, 0x16, 0xa7, 0xbd, + 0xb8, 0xbf, 0xae, 0x56, 0x8e, 0xb1, 0xb1, 0x2c, 0xa5, 0xd6, 0xf6, 0x42, 0x7e, 0x1c, 0x89, 0xd1, + 0x9e, 0xe4, 0x3d, 0x08, 0x63, 0x8f, 0x7e, 0x04, 0x8b, 0x4c, 0x6e, 0xe4, 0x78, 0x4a, 0x5c, 0xab, + 0xa2, 0x27, 0x39, 0xef, 0x2e, 0x48, 0x55, 0x8b, 0x31, 0x84, 0xe1, 0x54, 0x62, 0xa6, 0x83, 0x67, + 0xa7, 0xea, 0xe0, 0x42, 0xfe, 0x4b, 0x3b, 0xd8, 0x87, 0x71, 0x09, 0x44, 0x3f, 0x84, 0xba, 0xeb, + 0x91, 0x0f, 0x02, 0x2a, 0xb3, 0xf2, 0x8c, 0x0b, 0xee, 0x9e, 0xa0, 0x1d, 0x57, 0x26, 0x10, 0xea, + 0x8c, 0xd0, 0x58, 0x8a, 0xd4, 0x1e, 0x29, 0xb0, 0x56, 0x1c, 0x66, 0x53, 0x4c, 0x8b, 0x7d, 0x58, + 0xe9, 0x11, 0x6e, 0x1e, 0x27, 0x0b, 0x45, 0xb4, 0xd0, 0xa2, 0xb1, 0x39, 0x1c, 0xb4, 0x56, 0xee, + 0xe4, 0x30, 0x67, 0x83, 0x16, 0x7a, 0x3b, 0xb0, 0xed, 0xd3, 0xfc, 0xcd, 0x58, 0xe0, 0xd7, 0x7e, + 0xa9, 0xc2, 0x72, 0x6e, 0x76, 0x57, 0xb8, 0x8e, 0xb6, 0x60, 0xb5, 0x93, 0x06, 0x3b, 0x44, 0x48, + 0x33, 0xbe, 0x22, 0x89, 0xb3, 0x95, 0x22, 0xf8, 0x8a, 0xf4, 0xf9, 0xd2, 0x51, 0x3f, 0xf3, 0xd2, + 0x79, 0x00, 0x2b, 0x24, 0xd9, 0xd6, 0x77, 0xdc, 0x0e, 0x95, 0xbb, 0x52, 0x97, 0x5c, 0x2b, 0x5b, + 0x39, 0xec, 0xd9, 0xa0, 0xf5, 0xa5, 0xe2, 0x8e, 0x0f, 0xe1, 0xb8, 0x20, 0x05, 0xbd, 0x00, 0x35, + 0xd3, 0x0d, 0x1c, 0x2e, 0x16, 0xaa, 0x9a, 0xb6, 0xca, 0x76, 0x08, 0xc4, 0x11, 0x0e, 0x7d, 0x0b, + 0x1a, 0xa4, 0xd3, 0xb3, 0x9c, 0x2d, 0xd3, 0xa4, 0x8c, 0xad, 0xd7, 0xc5, 0x2a, 0x4f, 0x16, 0xd6, + 0x56, 0x8a, 0xc2, 0x59, 0x3a, 0xed, 0xbf, 0x4a, 0x7c, 0x27, 0x96, 0xdc, 0x33, 0xe8, 0x6a, 0x78, + 0x1d, 0x09, 0x94, 0x4c, 0x4e, 0xe6, 0xc0, 0x11, 0x60, 0x1c, 0xe3, 0xd1, 0x37, 0xa0, 0xde, 0xf1, + 0xad, 0x3e, 0xf5, 0x65, 0x66, 0x92, 0x1e, 0xd8, 0x11, 0x50, 0x2c, 0xb1, 0x61, 0xb2, 0xbd, 0xf8, + 0xde, 0xc8, 0x24, 0x7b, 0xdf, 0x75, 0x6d, 0x2c, 0x30, 0x42, 0x92, 0xb0, 0x4a, 0x86, 0x30, 0x95, + 0x14, 0xd9, 0x2a, 0xb1, 0xe8, 0x7a, 0xde, 0xeb, 0x9a, 0xf0, 0x7a, 0x75, 0xa2, 0xc7, 0xef, 0xc1, + 0x4a, 0xe1, 0xae, 0xbf, 0x05, 0xaa, 0x49, 0x6d, 0xd9, 0x78, 0xed, 0xc9, 0x05, 0x31, 0xf2, 0x56, + 0x60, 0xcc, 0x0f, 0x07, 0x2d, 0x75, 0x7b, 0xf7, 0x36, 0x0e, 0x85, 0x68, 0xbf, 0x55, 0xe0, 0x52, + 0x69, 0x73, 0x66, 0x02, 0xa4, 0x4c, 0x0c, 0x10, 0x01, 0xf0, 0x88, 0x4f, 0x7a, 0x94, 0x53, 0x9f, + 0x8d, 0x59, 0x58, 0xf9, 0x39, 0x2d, 0x5f, 0xbe, 0x75, 0x4c, 0x7e, 0xb6, 0xfb, 0x21, 0xa7, 0x4e, + 0x78, 0x5b, 0xa5, 0xbb, 0x70, 0x3f, 0x11, 0x84, 0x33, 0x42, 0xb5, 0xdf, 0xcc, 0xc2, 0x32, 0x96, + 0xee, 0x45, 0xd7, 0xd7, 0xff, 0x7f, 0x03, 0xdf, 0xcf, 0x6d, 0xe0, 0x67, 0x44, 0x3a, 0x67, 0x5c, + 0xd9, 0x0e, 0x46, 0x0f, 0xc3, 0xbb, 0x94, 0xf0, 0x80, 0x55, 0x7b, 0x97, 0xc8, 0x0b, 0x15, 0x8c, + 0x69, 0x12, 0xa2, 0x67, 0x2c, 0x05, 0x6a, 0x43, 0x05, 0x9a, 0x39, 0xfa, 0x70, 0x78, 0x06, 0x3d, + 0xea, 0x63, 0x7a, 0x44, 0x7d, 0xea, 0x98, 0x14, 0x5d, 0x83, 0x05, 0xe2, 0x59, 0x37, 0x7d, 0x37, + 0xf0, 0x64, 0x46, 0x93, 0xed, 0xb8, 0xb5, 0xbf, 0x27, 0xe0, 0x38, 0xa1, 0x08, 0xa9, 0x63, 0x8b, + 0x64, 0xe9, 0x67, 0x2e, 0xd6, 0x08, 0x8e, 0x13, 0x8a, 0x64, 0x22, 0xce, 0x95, 0x4e, 0x44, 0x03, + 0xd4, 0xc0, 0xea, 0xc8, 0x33, 0xfb, 0x15, 0x49, 0xa0, 0xbe, 0xbb, 0xb7, 0x73, 0x36, 0x68, 0x5d, + 0x29, 0xfb, 0x52, 0xc3, 0x4f, 0x3d, 0xca, 0xf4, 0x77, 0xf7, 0x76, 0x70, 0xc8, 0xac, 0xfd, 0x59, + 0x81, 0x0b, 0x39, 0x27, 0xcf, 0xe1, 0x4a, 0xd8, 0xcf, 0x5f, 0x09, 0x2f, 0x4d, 0x91, 0xb2, 0x92, + 0x3b, 0xc1, 0x2a, 0x38, 0x21, 0x0e, 0x85, 0x77, 0x8a, 0xdf, 0x97, 0xae, 0x56, 0x3e, 0xc6, 0xcb, + 0x3f, 0x2a, 0x69, 0xff, 0x51, 0xe0, 0xe2, 0x98, 0x2a, 0x42, 0xef, 0x03, 0xa4, 0x63, 0x7b, 0x4c, + 0xd0, 0xc6, 0x28, 0x1c, 0x79, 0x75, 0x5c, 0x11, 0x5f, 0x7d, 0x52, 0x68, 0x46, 0x22, 0x62, 0xd0, + 0xf0, 0x29, 0xa3, 0x7e, 0x9f, 0x76, 0xde, 0x76, 0x7d, 0x19, 0xba, 0xef, 0x4e, 0x11, 0xba, 0x91, + 0xea, 0x4d, 0xb7, 0x03, 0x4e, 0x05, 0xe3, 0xac, 0x16, 0xed, 0x1f, 0x0a, 0x7c, 0x39, 0x27, 0xe4, + 0x1d, 0xda, 0xf3, 0x6c, 0xc2, 0xe9, 0x39, 0x0c, 0x8b, 0x87, 0xb9, 0x61, 0xf1, 0xc6, 0x14, 0x9e, + 0xc6, 0x46, 0x96, 0x1e, 0xee, 0x7f, 0x57, 0xe0, 0xd2, 0x58, 0x8e, 0x73, 0x28, 0xfe, 0xef, 0xe7, + 0x8b, 0xff, 0xd5, 0x4f, 0xe1, 0x57, 0xf9, 0xb1, 0x7c, 0xa9, 0x34, 0x0e, 0x5f, 0xc8, 0xe9, 0xae, + 0xfd, 0x41, 0x81, 0xa5, 0x98, 0x32, 0xbc, 0x0e, 0x2a, 0x9c, 0x89, 0x37, 0x00, 0xe4, 0xd7, 0xe7, + 0xf8, 0x85, 0x56, 0x4d, 0xed, 0xbe, 0x99, 0x60, 0x70, 0x86, 0x0a, 0xdd, 0x02, 0x14, 0x5b, 0x78, + 0x60, 0x8b, 0xa5, 0x1d, 0x5e, 0x5b, 0xaa, 0xe0, 0xdd, 0x90, 0xbc, 0x08, 0x8f, 0x50, 0xe0, 0x31, + 0x5c, 0xda, 0x5f, 0x94, 0x74, 0xaf, 0x0a, 0xf0, 0xe7, 0x35, 0xf2, 0xc2, 0xb8, 0xd2, 0xc8, 0x67, + 0xf7, 0x82, 0xa0, 0xfc, 0xdc, 0xee, 0x05, 0x61, 0x5d, 0x49, 0x4b, 0x3c, 0x52, 0x0b, 0x5e, 0x88, + 0x56, 0xa8, 0x7a, 0x85, 0xdd, 0x96, 0x67, 0x6a, 0x14, 0xd6, 0x17, 0xab, 0x99, 0x13, 0x96, 0xe9, + 0xd8, 0x93, 0xf6, 0x1a, 0x2c, 0x38, 0x6e, 0x87, 0x8a, 0x17, 0x97, 0xc2, 0xf6, 0xbf, 0x2b, 0xe1, + 0x38, 0xa1, 0x18, 0xf9, 0xef, 0x62, 0xee, 0xb3, 0xf9, 0xef, 0x42, 0x5c, 0x2c, 0xb6, 0x1d, 0x12, + 0xc4, 0xd7, 0x72, 0x7a, 0xb1, 0x48, 0x38, 0x4e, 0x28, 0xd0, 0xbd, 0x74, 0x85, 0xd6, 0x45, 0x4e, + 0xbe, 0x5e, 0x65, 0x85, 0x96, 0x6f, 0x4f, 0xc3, 0x78, 0xfc, 0xb4, 0x39, 0xf3, 0xe4, 0x69, 0x73, + 0xe6, 0xe3, 0xa7, 0xcd, 0x99, 0x8f, 0x86, 0x4d, 0xe5, 0xf1, 0xb0, 0xa9, 0x3c, 0x19, 0x36, 0x95, + 0x8f, 0x87, 0x4d, 0xe5, 0x93, 0x61, 0x53, 0xf9, 0xd5, 0xbf, 0x9a, 0x33, 0x3f, 0x78, 0x7e, 0xd2, + 0x5f, 0x74, 0xff, 0x0b, 0x00, 0x00, 0xff, 0xff, 0x1a, 0xa5, 0x7d, 0xad, 0xc1, 0x1b, 0x00, 0x00, } func (m *AllocationResult) Marshal() (dAtA []byte, err error) { @@ -1857,6 +1857,16 @@ func (m *DeviceRequestAllocationResult) MarshalToSizedBuffer(dAtA []byte) (int, _ = i var l int _ = l + if m.AdminAccess != nil { + i-- + if *m.AdminAccess { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x28 + } i -= len(m.Device) copy(dAtA[i:], m.Device) i = encodeVarintGenerated(dAtA, i, uint64(len(m.Device))) @@ -2829,6 +2839,9 @@ func (m *DeviceRequestAllocationResult) Size() (n int) { n += 1 + l + sovGenerated(uint64(l)) l = len(m.Device) n += 1 + l + sovGenerated(uint64(l)) + if m.AdminAccess != nil { + n += 2 + } return n } @@ -3310,6 +3323,7 @@ func (this *DeviceRequestAllocationResult) String() string { `Driver:` + fmt.Sprintf("%v", this.Driver) + `,`, `Pool:` + fmt.Sprintf("%v", this.Pool) + `,`, `Device:` + fmt.Sprintf("%v", this.Device) + `,`, + `AdminAccess:` + valueToStringGenerated(this.AdminAccess) + `,`, `}`, }, "") return s @@ -5834,6 +5848,27 @@ func (m *DeviceRequestAllocationResult) Unmarshal(dAtA []byte) error { } m.Device = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AdminAccess", wireType) + } + var v int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenerated + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + b := bool(v != 0) + m.AdminAccess = &b default: iNdEx = preIndex skippy, err := skipGenerated(dAtA[iNdEx:]) diff --git a/staging/src/k8s.io/api/resource/v1alpha3/generated.proto b/staging/src/k8s.io/api/resource/v1alpha3/generated.proto index b549fe3f8f7..3e093dd739f 100644 --- a/staging/src/k8s.io/api/resource/v1alpha3/generated.proto +++ b/staging/src/k8s.io/api/resource/v1alpha3/generated.proto @@ -453,6 +453,17 @@ message DeviceRequestAllocationResult { // // +required optional string device = 4; + + // AdminAccess is a copy of the AdminAccess value in the + // request which caused this device to be allocated. + // + // New allocations are required to have this set. Old allocations made + // by Kubernetes 1.31 do not have it yet. Clients which want to + // support Kubernetes 1.31 need to look up the request and retrieve + // the value from there if this field is not set. + // + // +required + optional bool adminAccess = 5; } // DeviceSelector must have exactly one field set. diff --git a/staging/src/k8s.io/api/resource/v1alpha3/types.go b/staging/src/k8s.io/api/resource/v1alpha3/types.go index 5bb9cdbdbd0..71b0d2fc670 100644 --- a/staging/src/k8s.io/api/resource/v1alpha3/types.go +++ b/staging/src/k8s.io/api/resource/v1alpha3/types.go @@ -788,6 +788,17 @@ type DeviceRequestAllocationResult struct { // // +required Device string `json:"device" protobuf:"bytes,4,name=device"` + + // AdminAccess is a copy of the AdminAccess value in the + // request which caused this device to be allocated. + // + // New allocations are required to have this set. Old allocations made + // by Kubernetes 1.31 do not have it yet. Clients which want to + // support Kubernetes 1.31 need to look up the request and retrieve + // the value from there if this field is not set. + // + // +required + AdminAccess *bool `json:"adminAccess" protobuf:"bytes,5,name=adminAccess"` } // DeviceAllocationConfiguration gets embedded in an AllocationResult. diff --git a/staging/src/k8s.io/api/resource/v1alpha3/types_swagger_doc_generated.go b/staging/src/k8s.io/api/resource/v1alpha3/types_swagger_doc_generated.go index a5ff1ad6f97..0fd2ff052dd 100644 --- a/staging/src/k8s.io/api/resource/v1alpha3/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/resource/v1alpha3/types_swagger_doc_generated.go @@ -190,11 +190,12 @@ func (DeviceRequest) SwaggerDoc() map[string]string { } var map_DeviceRequestAllocationResult = map[string]string{ - "": "DeviceRequestAllocationResult contains the allocation result for one request.", - "request": "Request is the name of the request in the claim which caused this device to be allocated. Multiple devices may have been allocated per request.", - "driver": "Driver specifies the name of the DRA driver whose kubelet plugin should be invoked to process the allocation once the claim is needed on a node.\n\nMust be a DNS subdomain and should end with a DNS domain owned by the vendor of the driver.", - "pool": "This name together with the driver name and the device name field identify which device was allocated (`//`).\n\nMust not be longer than 253 characters and may contain one or more DNS sub-domains separated by slashes.", - "device": "Device references one device instance via its name in the driver's resource pool. It must be a DNS label.", + "": "DeviceRequestAllocationResult contains the allocation result for one request.", + "request": "Request is the name of the request in the claim which caused this device to be allocated. Multiple devices may have been allocated per request.", + "driver": "Driver specifies the name of the DRA driver whose kubelet plugin should be invoked to process the allocation once the claim is needed on a node.\n\nMust be a DNS subdomain and should end with a DNS domain owned by the vendor of the driver.", + "pool": "This name together with the driver name and the device name field identify which device was allocated (`//`).\n\nMust not be longer than 253 characters and may contain one or more DNS sub-domains separated by slashes.", + "device": "Device references one device instance via its name in the driver's resource pool. It must be a DNS label.", + "adminAccess": "AdminAccess is a copy of the AdminAccess value in the request which caused this device to be allocated.\n\nNew allocations are required to have this set. Old allocations made by Kubernetes 1.31 do not have it yet. Clients which want to support Kubernetes 1.31 need to look up the request and retrieve the value from there if this field is not set.", } func (DeviceRequestAllocationResult) SwaggerDoc() map[string]string { diff --git a/staging/src/k8s.io/api/resource/v1alpha3/zz_generated.deepcopy.go b/staging/src/k8s.io/api/resource/v1alpha3/zz_generated.deepcopy.go index b951d76aa04..a88bb5dec27 100644 --- a/staging/src/k8s.io/api/resource/v1alpha3/zz_generated.deepcopy.go +++ b/staging/src/k8s.io/api/resource/v1alpha3/zz_generated.deepcopy.go @@ -144,7 +144,9 @@ func (in *DeviceAllocationResult) DeepCopyInto(out *DeviceAllocationResult) { if in.Results != nil { in, out := &in.Results, &out.Results *out = make([]DeviceRequestAllocationResult, len(*in)) - copy(*out, *in) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } if in.Config != nil { in, out := &in.Config, &out.Config @@ -441,6 +443,11 @@ func (in *DeviceRequest) DeepCopy() *DeviceRequest { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DeviceRequestAllocationResult) DeepCopyInto(out *DeviceRequestAllocationResult) { *out = *in + if in.AdminAccess != nil { + in, out := &in.AdminAccess, &out.AdminAccess + *out = new(bool) + **out = **in + } return } diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.json b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.json index 131328e42d4..d64766cc66c 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.json +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.json @@ -99,7 +99,8 @@ "request": "requestValue", "driver": "driverValue", "pool": "poolValue", - "device": "deviceValue" + "device": "deviceValue", + "adminAccess": true } ], "config": [ diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.pb b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.pb index 7bac0d15d7a..6518cf12480 100644 Binary files a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.pb and b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.pb differ diff --git a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.yaml b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.yaml index 26f136171bb..640f9427b90 100644 --- a/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.yaml +++ b/staging/src/k8s.io/api/testdata/HEAD/resource.k8s.io.v1alpha3.ResourceClaim.yaml @@ -76,7 +76,8 @@ status: - requestsValue source: sourceValue results: - - device: deviceValue + - adminAccess: true + device: deviceValue driver: driverValue pool: poolValue request: requestValue diff --git a/staging/src/k8s.io/api/testdata/v1.31.0/resource.k8s.io.v1alpha3.ResourceClaim.after_roundtrip.json b/staging/src/k8s.io/api/testdata/v1.31.0/resource.k8s.io.v1alpha3.ResourceClaim.after_roundtrip.json index 131328e42d4..d14468fd1ff 100644 --- a/staging/src/k8s.io/api/testdata/v1.31.0/resource.k8s.io.v1alpha3.ResourceClaim.after_roundtrip.json +++ b/staging/src/k8s.io/api/testdata/v1.31.0/resource.k8s.io.v1alpha3.ResourceClaim.after_roundtrip.json @@ -99,7 +99,8 @@ "request": "requestValue", "driver": "driverValue", "pool": "poolValue", - "device": "deviceValue" + "device": "deviceValue", + "adminAccess": null } ], "config": [ diff --git a/staging/src/k8s.io/api/testdata/v1.31.0/resource.k8s.io.v1alpha3.ResourceClaim.after_roundtrip.yaml b/staging/src/k8s.io/api/testdata/v1.31.0/resource.k8s.io.v1alpha3.ResourceClaim.after_roundtrip.yaml index 26f136171bb..7ddd6d9c06c 100644 --- a/staging/src/k8s.io/api/testdata/v1.31.0/resource.k8s.io.v1alpha3.ResourceClaim.after_roundtrip.yaml +++ b/staging/src/k8s.io/api/testdata/v1.31.0/resource.k8s.io.v1alpha3.ResourceClaim.after_roundtrip.yaml @@ -76,7 +76,8 @@ status: - requestsValue source: sourceValue results: - - device: deviceValue + - adminAccess: null + device: deviceValue driver: driverValue pool: poolValue request: requestValue diff --git a/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go b/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go index c5c674fcd53..397b45e092f 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/internal/internal.go @@ -12443,6 +12443,9 @@ var schemaYAML = typed.YAMLObject(`types: - name: io.k8s.api.resource.v1alpha3.DeviceRequestAllocationResult map: fields: + - name: adminAccess + type: + scalar: boolean - name: device type: scalar: string diff --git a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha3/devicerequestallocationresult.go b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha3/devicerequestallocationresult.go index 712b9bf9b18..4c3cffcf465 100644 --- a/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha3/devicerequestallocationresult.go +++ b/staging/src/k8s.io/client-go/applyconfigurations/resource/v1alpha3/devicerequestallocationresult.go @@ -21,10 +21,11 @@ package v1alpha3 // DeviceRequestAllocationResultApplyConfiguration represents a declarative configuration of the DeviceRequestAllocationResult type for use // with apply. type DeviceRequestAllocationResultApplyConfiguration struct { - Request *string `json:"request,omitempty"` - Driver *string `json:"driver,omitempty"` - Pool *string `json:"pool,omitempty"` - Device *string `json:"device,omitempty"` + Request *string `json:"request,omitempty"` + Driver *string `json:"driver,omitempty"` + Pool *string `json:"pool,omitempty"` + Device *string `json:"device,omitempty"` + AdminAccess *bool `json:"adminAccess,omitempty"` } // DeviceRequestAllocationResultApplyConfiguration constructs a declarative configuration of the DeviceRequestAllocationResult type for use with @@ -64,3 +65,11 @@ func (b *DeviceRequestAllocationResultApplyConfiguration) WithDevice(value strin b.Device = &value return b } + +// WithAdminAccess sets the AdminAccess field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the AdminAccess field is set to the value of the last call. +func (b *DeviceRequestAllocationResultApplyConfiguration) WithAdminAccess(value bool) *DeviceRequestAllocationResultApplyConfiguration { + b.AdminAccess = &value + return b +} diff --git a/staging/src/k8s.io/dynamic-resource-allocation/structured/allocator.go b/staging/src/k8s.io/dynamic-resource-allocation/structured/allocator.go index 271fe064557..2b852c01046 100644 --- a/staging/src/k8s.io/dynamic-resource-allocation/structured/allocator.go +++ b/staging/src/k8s.io/dynamic-resource-allocation/structured/allocator.go @@ -273,6 +273,15 @@ func (a *Allocator) Allocate(ctx context.Context, node *v1.Node) (finalResult [] continue } for _, result := range claim.Status.Allocation.Devices.Results { + // Kubernetes 1.31 did not set this, 1.32 always does. + // Supporting 1.31 is not worth the additional code that + // would have to be written (= looking up in request) because + // it is extremely unlikely that there really is a result + // that still exists in a cluster from 1.31 where this matters. + if ptr.Deref(result.AdminAccess, false) { + // Ignore, it's not considered allocated. + continue + } deviceID := DeviceID{Driver: result.Driver, Pool: result.Pool, Device: result.Device} alloc.allocated[deviceID] = true numAllocated++ @@ -735,10 +744,11 @@ func (alloc *allocator) allocateDevice(r deviceIndices, device *resourceapi.Basi alloc.allocated[deviceID] = true } result := resourceapi.DeviceRequestAllocationResult{ - Request: request.Name, - Driver: deviceID.Driver, - Pool: deviceID.Pool, - Device: deviceID.Device, + Request: request.Name, + Driver: deviceID.Driver, + Pool: deviceID.Pool, + Device: deviceID.Device, + AdminAccess: &request.AdminAccess, } previousNumResults := len(alloc.result[r.claimIndex].Devices.Results) alloc.result[r.claimIndex].Devices.Results = append(alloc.result[r.claimIndex].Devices.Results, result) diff --git a/staging/src/k8s.io/dynamic-resource-allocation/structured/allocator_test.go b/staging/src/k8s.io/dynamic-resource-allocation/structured/allocator_test.go index 8626302418f..a8610db1364 100644 --- a/staging/src/k8s.io/dynamic-resource-allocation/structured/allocator_test.go +++ b/staging/src/k8s.io/dynamic-resource-allocation/structured/allocator_test.go @@ -241,13 +241,15 @@ func slice(name string, nodeSelection any, pool, driver string, devices ...resou return slice } -func deviceAllocationResult(request, driver, pool, device string) resourceapi.DeviceRequestAllocationResult { - return resourceapi.DeviceRequestAllocationResult{ +func deviceAllocationResult(request, driver, pool, device string, adminAccess bool) resourceapi.DeviceRequestAllocationResult { + r := resourceapi.DeviceRequestAllocationResult{ Request: request, Driver: driver, Pool: pool, Device: device, } + r.AdminAccess = &adminAccess + return r } // nodeLabelSelector creates a node selector with a label match for "key" in "values". @@ -375,7 +377,7 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), )}, }, "other-node": { @@ -389,7 +391,7 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node2), - deviceAllocationResult(req0, driverA, pool2, device1), + deviceAllocationResult(req0, driverA, pool2, device1, false), )}, }, "small-and-large": { @@ -418,8 +420,8 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req1, driverA, pool1, device2), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req1, driverA, pool1, device2, false), )}, }, "small-and-large-backtrack-requests": { @@ -451,8 +453,8 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req1, driverA, pool1, device2), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req1, driverA, pool1, device2, false), )}, }, "small-and-large-backtrack-claims": { @@ -487,8 +489,8 @@ func TestAllocator(t *testing.T) { node: node(node1, region1), expectResults: []any{ - allocationResult(localNodeSelector(node1), deviceAllocationResult(req0, driverA, pool1, device1)), - allocationResult(localNodeSelector(node1), deviceAllocationResult(req1, driverA, pool1, device2)), + allocationResult(localNodeSelector(node1), deviceAllocationResult(req0, driverA, pool1, device1, false)), + allocationResult(localNodeSelector(node1), deviceAllocationResult(req1, driverA, pool1, device2, false)), }, }, "devices-split-across-different-slices": { @@ -507,8 +509,8 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req0, driverA, pool2, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req0, driverA, pool2, device1, false), )}, }, "obsolete-slice": { @@ -527,7 +529,7 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), )}, }, "no-slices": { @@ -594,7 +596,7 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), )}, }, "all-devices-many": { @@ -612,8 +614,8 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req0, driverA, pool2, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req0, driverA, pool2, device1, false), )}, }, "all-devices-of-the-incomplete-pool": { @@ -664,11 +666,11 @@ func TestAllocator(t *testing.T) { expectResults: []any{ allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), ), allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverB, pool1, device1), + deviceAllocationResult(req0, driverB, pool1, device1, false), ), }, }, @@ -699,11 +701,11 @@ func TestAllocator(t *testing.T) { expectResults: []any{ allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverB, pool1, device1), + deviceAllocationResult(req0, driverB, pool1, device1, false), ), allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), ), }, }, @@ -737,12 +739,12 @@ func TestAllocator(t *testing.T) { expectResults: []any{ allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req0, driverA, pool1, device2), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req0, driverA, pool1, device2, false), ), allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverB, pool1, device1), + deviceAllocationResult(req0, driverB, pool1, device1, false), ), }, }, @@ -776,12 +778,12 @@ func TestAllocator(t *testing.T) { expectResults: []any{ allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverB, pool1, device1), + deviceAllocationResult(req0, driverB, pool1, device1, false), ), allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req0, driverA, pool1, device2), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req0, driverA, pool1, device2, false), ), }, }, @@ -839,7 +841,7 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( nodeLabelSelector(regionKey, region1), - deviceAllocationResult(req0, driverA, pool1, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), )}, }, "unsuccessful-allocation-network-attached-device": { @@ -875,10 +877,10 @@ func TestAllocator(t *testing.T) { }, }}, }, - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req0, driverA, pool2, device1), - deviceAllocationResult(req0, driverA, pool3, device1), - deviceAllocationResult(req0, driverA, pool4, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req0, driverA, pool2, device1, false), + deviceAllocationResult(req0, driverA, pool3, device1, false), + deviceAllocationResult(req0, driverA, pool4, device1, false), )}, }, "local-and-network-attached-devices": { @@ -893,8 +895,8 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( // Once there is any node-local device, the selector is for that node. localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req0, driverA, pool2, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req0, driverA, pool2, device1, false), )}, }, "several-different-drivers": { @@ -910,16 +912,16 @@ func TestAllocator(t *testing.T) { node: node(node1, region1), expectResults: []any{ - allocationResult(localNodeSelector(node1), deviceAllocationResult(req0, driverA, pool1, device1)), - allocationResult(localNodeSelector(node1), deviceAllocationResult(req0, driverB, pool1, device1)), + allocationResult(localNodeSelector(node1), deviceAllocationResult(req0, driverA, pool1, device1, false)), + allocationResult(localNodeSelector(node1), deviceAllocationResult(req0, driverB, pool1, device1, false)), }, }, "already-allocated-devices": { claimsToAllocate: objects(claim(claim0, req0, classA)), allocatedClaims: objects( allocatedClaim(claim0, req0, classA, - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req1, driverA, pool1, device2), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req1, driverA, pool1, device2, false), ), ), classes: objects(class(classA, driverA)), @@ -928,6 +930,42 @@ func TestAllocator(t *testing.T) { expectResults: nil, }, + "admin-access": { + claimsToAllocate: func() []*resourceapi.ResourceClaim { + c := claim(claim0, req0, classA) + c.Spec.Devices.Requests[0].AdminAccess = true + return []*resourceapi.ResourceClaim{c} + }(), + allocatedClaims: objects( + allocatedClaim(claim0, req0, classA, + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req1, driverA, pool1, device2, false), + ), + ), + classes: objects(class(classA, driverA)), + slices: objects(sliceWithOneDevice(slice1, node1, pool1, driverA)), + node: node(node1, region1), + + expectResults: []any{ + allocationResult(localNodeSelector(node1), deviceAllocationResult(req0, driverA, pool1, device1, true)), + }, + }, + "already-allocated-for-admin-access": { + claimsToAllocate: objects(claim(claim0, req0, classA)), + allocatedClaims: objects( + allocatedClaim(claim0, req0, classA, + deviceAllocationResult(req0, driverA, pool1, device1, true), + deviceAllocationResult(req1, driverA, pool1, device2, true), + ), + ), + classes: objects(class(classA, driverA)), + slices: objects(sliceWithOneDevice(slice1, node1, pool1, driverA)), + node: node(node1, region1), + + expectResults: []any{ + allocationResult(localNodeSelector(node1), deviceAllocationResult(req0, driverA, pool1, device1, false)), + }, + }, "with-constraint": { claimsToAllocate: objects(claimWithRequests( claim0, @@ -960,8 +998,8 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req1, driverA, pool1, device2), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req1, driverA, pool1, device2, false), )}, }, "with-constraint-non-existent-attribute": { @@ -1100,8 +1138,8 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device1), - deviceAllocationResult(req1, driverA, pool1, device2), + deviceAllocationResult(req0, driverA, pool1, device1, false), + deviceAllocationResult(req1, driverA, pool1, device2, false), )}, }, "with-constraint-for-request-retry": { @@ -1141,8 +1179,8 @@ func TestAllocator(t *testing.T) { expectResults: []any{allocationResult( localNodeSelector(node1), - deviceAllocationResult(req0, driverA, pool1, device2), - deviceAllocationResult(req1, driverA, pool1, device3), + deviceAllocationResult(req0, driverA, pool1, device2, false), + deviceAllocationResult(req1, driverA, pool1, device3, false), )}, }, "with-class-device-config": { @@ -1157,7 +1195,7 @@ func TestAllocator(t *testing.T) { driverA, resourceapi.AllocationConfigSourceClass, "classAttribute", - deviceAllocationResult(req0, driverA, pool1, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), ), }, }, @@ -1173,7 +1211,7 @@ func TestAllocator(t *testing.T) { driverA, resourceapi.AllocationConfigSourceClaim, "deviceAttribute", - deviceAllocationResult(req0, driverA, pool1, device1), + deviceAllocationResult(req0, driverA, pool1, device1, false), ), }, }, diff --git a/test/e2e_node/dra_test.go b/test/e2e_node/dra_test.go index dcdbeb715d1..72ce7013762 100644 --- a/test/e2e_node/dra_test.go +++ b/test/e2e_node/dra_test.go @@ -47,6 +47,7 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/klog/v2" admissionapi "k8s.io/pod-security-admission/api" + "k8s.io/utils/ptr" "k8s.io/kubernetes/test/e2e/feature" "k8s.io/kubernetes/test/e2e/framework" @@ -673,10 +674,11 @@ func createTestObjects(ctx context.Context, clientSet kubernetes.Interface, node config := make([]resourceapi.DeviceAllocationConfiguration, len(driverNames)) for i, driverName := range driverNames { results[i] = resourceapi.DeviceRequestAllocationResult{ - Driver: driverName, - Pool: "some-pool", - Device: "some-device", - Request: claim.Spec.Devices.Requests[0].Name, + Driver: driverName, + Pool: "some-pool", + Device: "some-device", + Request: claim.Spec.Devices.Requests[0].Name, + AdminAccess: ptr.To(false), } config[i] = resourceapi.DeviceAllocationConfiguration{ Source: resourceapi.AllocationConfigSourceClaim,