Skip to content

Commit 13a7359

Browse files
authored
Merge pull request #587 from jgehrcke/jp/strict-decode-on-prepres
kubelet plugins: re-introduce strict decoding in NodePrepareResources and webhook
2 parents 0474420 + 2d2b342 commit 13a7359

File tree

4 files changed

+40
-22
lines changed

4 files changed

+40
-22
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
@@ -277,8 +277,10 @@ func (s *DeviceState) updateCheckpoint(f func(*Checkpoint)) error {
277277
}
278278

279279
func (s *DeviceState) prepareDevices(ctx context.Context, claim *resourceapi.ResourceClaim) (PreparedDevices, error) {
280-
// Generate a mapping of each OpaqueDeviceConfigs to the Device.Results it applies to
281-
configResultsMap, err := s.getConfigResultsMap(&claim.Status)
280+
// Generate a mapping of each OpaqueDeviceConfigs to the Device.Results it
281+
// applies to. Strict-decode: data is provided by user and may be completely
282+
// unvalidated so far (in absence of validating webhook).
283+
configResultsMap, err := s.getConfigResultsMap(&claim.Status, configapi.StrictDecoder)
282284
if err != nil {
283285
return nil, fmt.Errorf("error generating configResultsMap: %w", err)
284286
}
@@ -366,8 +368,11 @@ func (s *DeviceState) prepareDevices(ctx context.Context, claim *resourceapi.Res
366368
}
367369

368370
func (s *DeviceState) unprepareDevices(ctx context.Context, cs *resourceapi.ResourceClaimStatus) error {
369-
// Generate a mapping of each OpaqueDeviceConfigs to the Device.Results it applies to
370-
configResultsMap, err := s.getConfigResultsMap(cs)
371+
// Generate a mapping of each OpaqueDeviceConfigs to the Device.Results it
372+
// applies to. Non-strict decoding: do not error out on unknown fields (data
373+
// source is checkpointed JSON written by potentially newer versions of this
374+
// driver).
375+
configResultsMap, err := s.getConfigResultsMap(cs, configapi.NonstrictDecoder)
371376
if err != nil {
372377
return fmt.Errorf("error generating configResultsMap: %w", err)
373378
}
@@ -496,10 +501,10 @@ func (s *DeviceState) applyComputeDomainDaemonConfig(ctx context.Context, config
496501
return &configState, nil
497502
}
498503

499-
func (s *DeviceState) getConfigResultsMap(rcs *resourceapi.ResourceClaimStatus) (map[runtime.Object][]*resourceapi.DeviceRequestAllocationResult, error) {
504+
func (s *DeviceState) getConfigResultsMap(rcs *resourceapi.ResourceClaimStatus, decoder runtime.Decoder) (map[runtime.Object][]*resourceapi.DeviceRequestAllocationResult, error) {
500505
// Retrieve the full set of device configs for the driver.
501506
configs, err := GetOpaqueDeviceConfigs(
502-
configapi.Decoder,
507+
decoder,
503508
DriverName,
504509
rcs.Allocation.Devices.Config,
505510
)

cmd/gpu-kubelet-plugin/device_state.go

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

266266
// Retrieve the full set of device configs for the driver.
267267
configs, err := GetOpaqueDeviceConfigs(
268-
configapi.Decoder,
268+
configapi.StrictDecoder,
269269
DriverName,
270270
claim.Status.Allocation.Devices.Config,
271271
)

cmd/webhook/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,8 @@ func admitResourceClaimParameters(ar admissionv1.AdmissionReview) *admissionv1.A
249249
}
250250

251251
fieldPath := fmt.Sprintf("%s.devices.config[%d].opaque.parameters", specPath, configIndex)
252-
decodedConfig, err := runtime.Decode(nvapi.Decoder, config.Opaque.Parameters.Raw)
252+
// Strict-decode: do not allow for users to provide unknown fields.
253+
decodedConfig, err := runtime.Decode(nvapi.StrictDecoder, config.Opaque.Parameters.Raw)
253254
if err != nil {
254255
errs = append(errs, fmt.Errorf("error decoding object at %s: %w", fieldPath, err))
255256
continue

0 commit comments

Comments
 (0)