Skip to content

Commit 3751463

Browse files
committed
kubelet plugins: strict-decode opaque config in prepare path
Signed-off-by: Dr. Jan-Philip Gehrcke <[email protected]>
1 parent 7020737 commit 3751463

File tree

3 files changed

+38
-21
lines changed

3 files changed

+38
-21
lines changed

api/nvidia.com/resource/v1beta1/api.go

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,17 @@ type Interface interface {
4141
Validate() error
4242
}
4343

44-
// Decoder implements a decoder for objects in this API group.
45-
var Decoder runtime.Decoder
44+
// StrictDecoder implements a decoder for objects in this API group. Fails upon
45+
// unknown fields in the input. Is the preferable choice when processing input
46+
// directly provided by the user (example: opaque config JSON provided in a
47+
// resource claim, validated only in the NodePrepareResources code path when no
48+
// validating webhook is deployed).
49+
var StrictDecoder runtime.Decoder
50+
51+
// NonstrictDecoder implements a decoder for objects in this API group. Silently
52+
// drops unknown fields in the input. Used for deserializing checkpoint data
53+
// (JSON that may have been created by older or newer versions of this driver).
54+
var NonstrictDecoder runtime.Decoder
4655

4756
func init() {
4857
// Create a new scheme and add our types to it. If at some point in the
@@ -63,20 +72,23 @@ func init() {
6372
)
6473
metav1.AddToGroupVersion(scheme, schemeGroupVersion)
6574

66-
// Set up a json serializer to decode our types.
67-
Decoder = json.NewSerializerWithOptions(
75+
// Note: the strictness applies to all types defined above via
76+
// AddKnownTypes(), i.e. it cannot be set per-type. That is OK in this case.
77+
// Unknown fields will simply be dropped (ignored) upon decode, which is
78+
// what we want. This is relevant in a downgrade case, when a checkpointed
79+
// JSON document contains fields added in a later version (workload defined
80+
// with a new version of this driver).
81+
NonstrictDecoder = json.NewSerializerWithOptions(
82+
json.DefaultMetaFactory,
83+
scheme,
84+
scheme,
85+
json.SerializerOptions{Strict: false},
86+
)
87+
88+
StrictDecoder = json.NewSerializerWithOptions(
6889
json.DefaultMetaFactory,
6990
scheme,
7091
scheme,
71-
json.SerializerOptions{
72-
// Note: the strictness applies to all types defined above via
73-
// AddKnownTypes(), i.e. it cannot be set per-type. That is OK in
74-
// this case. Unknown fields will simply be dropped (ignored) upon
75-
// decode, which is what we want. This is relevant in a downgrade
76-
// case, when a checkpointed JSON document contains fields added in
77-
// a later version (workload defined with a new version of this
78-
// driver).
79-
Pretty: true, Strict: false,
80-
},
92+
json.SerializerOptions{Strict: true},
8193
)
8294
}

cmd/compute-domain-kubelet-plugin/device_state.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,10 @@ func (s *DeviceState) Unprepare(ctx context.Context, claimRef kubeletplugin.Name
236236
}
237237

238238
func (s *DeviceState) prepareDevices(ctx context.Context, claim *resourceapi.ResourceClaim) (PreparedDevices, error) {
239-
// Generate a mapping of each OpaqueDeviceConfigs to the Device.Results it applies to
240-
configResultsMap, err := s.getConfigResultsMap(&claim.Status)
239+
// Generate a mapping of each OpaqueDeviceConfigs to the Device.Results it
240+
// applies to. Strict-decode: data is provided by user and may be completely
241+
// unvalidated so far (in absence of validating webhook).
242+
configResultsMap, err := s.getConfigResultsMap(&claim.Status, configapi.StrictDecoder)
241243
if err != nil {
242244
return nil, fmt.Errorf("error generating configResultsMap: %w", err)
243245
}
@@ -325,8 +327,11 @@ func (s *DeviceState) prepareDevices(ctx context.Context, claim *resourceapi.Res
325327
}
326328

327329
func (s *DeviceState) unprepareDevices(ctx context.Context, cs *resourceapi.ResourceClaimStatus) error {
328-
// Generate a mapping of each OpaqueDeviceConfigs to the Device.Results it applies to
329-
configResultsMap, err := s.getConfigResultsMap(cs)
330+
// Generate a mapping of each OpaqueDeviceConfigs to the Device.Results it
331+
// applies to. Non-strict decoding: do not error out on unknown fields (data
332+
// source is checkpointed JSON written by potentially newer versions of this
333+
// driver).
334+
configResultsMap, err := s.getConfigResultsMap(cs, configapi.NonstrictDecoder)
330335
if err != nil {
331336
return fmt.Errorf("error generating configResultsMap: %w", err)
332337
}
@@ -447,10 +452,10 @@ func (s *DeviceState) applyComputeDomainDaemonConfig(ctx context.Context, config
447452
return &configState, nil
448453
}
449454

450-
func (s *DeviceState) getConfigResultsMap(rcs *resourceapi.ResourceClaimStatus) (map[runtime.Object][]*resourceapi.DeviceRequestAllocationResult, error) {
455+
func (s *DeviceState) getConfigResultsMap(rcs *resourceapi.ResourceClaimStatus, decoder runtime.Decoder) (map[runtime.Object][]*resourceapi.DeviceRequestAllocationResult, error) {
451456
// Retrieve the full set of device configs for the driver.
452457
configs, err := GetOpaqueDeviceConfigs(
453-
configapi.Decoder,
458+
decoder,
454459
DriverName,
455460
rcs.Allocation.Devices.Config,
456461
)

cmd/gpu-kubelet-plugin/device_state.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ func (s *DeviceState) prepareDevices(ctx context.Context, claim *resourceapi.Res
213213

214214
// Retrieve the full set of device configs for the driver.
215215
configs, err := GetOpaqueDeviceConfigs(
216-
configapi.Decoder,
216+
configapi.StrictDecoder,
217217
DriverName,
218218
claim.Status.Allocation.Devices.Config,
219219
)

0 commit comments

Comments
 (0)