From 2fb924f18eda2dae155215b47b2942f0ac934b07 Mon Sep 17 00:00:00 2001 From: cproudlock Date: Thu, 3 Sep 2026 15:16:33 -0400 Subject: [PATCH] Let a printer driver carry the name Windows actually matches on The driver form and the API both dropped `drivername` and `vendorid`. POST returned 201 with both null, PUT accepted them and stored nothing, and no screen offered either field - so there was no interface in the product that could set them. That is not a cosmetic gap. `drivername` is the exact string the INF declares, and Add-PrinterDriver matches on it; `name` is ours to choose and means nothing to Windows. With it null the shipped converger has nothing to match and installs nothing, and the drift check that compares an observed driver name against the expected one could never fire, because the expected value was never stored. `vendorid` is how a universal driver (HP UPD, Xerox GPD) attaches to a whole make instead of needing a near-duplicate row per model. Both are now read on create and update, and the driver form gained the two fields with hints saying what they are for - the INF name box says plainly that leaving it blank means the converger cannot install that driver. A whitespace value clears rather than stores: an empty box means "not known", and a blank string would look set and match nothing. Three tests. Verified by planting: drop the two fields from the create path again and the round-trip test fails. Scope: product --- plugins/printers/api/asset_routes.py | 17 +++++- .../frontend/views/PrinterDriversList.vue | 43 ++++++++++++-- .../test_printer_driver_resolution.py | 57 +++++++++++++++++++ 3 files changed, 110 insertions(+), 7 deletions(-) diff --git a/plugins/printers/api/asset_routes.py b/plugins/printers/api/asset_routes.py index f52fa508..5a1f0027 100644 --- a/plugins/printers/api/asset_routes.py +++ b/plugins/printers/api/asset_routes.py @@ -163,10 +163,20 @@ def create_driver(): data = request.get_json() or {} if not (data.get('name') and data.get('location')): return error_response(ErrorCodes.VALIDATION_ERROR, 'name and location are required') + # drivername and vendorid are accepted here because they are the two + # fields the converger actually uses. drivername is the exact string from + # the INF that Add-PrinterDriver matches on - `name` is ours to choose and + # means nothing to Windows - and vendorid attaches a universal driver to a + # whole make. Neither was read from the payload, so both came back null on + # a 201 and there was no way to set them through any interface: the + # converger had nothing to match and installed nothing, and driver-name + # drift could never be detected because the expected value was never there. d = PrinterDriver( name=data['name'], location=data['location'], description=data.get('description'), + drivername=(data.get('drivername') or '').strip() or None, + vendorid=data.get('vendorid') or None, modelnumberid=data.get('modelnumberid') or None, isactive=data.get('isactive', True), ) @@ -185,8 +195,11 @@ def update_driver(driver_id): for key in ('name', 'location', 'description', 'isactive'): if key in data: setattr(d, key, data[key]) - if 'modelnumberid' in data: - d.modelnumberid = data['modelnumberid'] or None + if 'drivername' in data: + d.drivername = (data['drivername'] or '').strip() or None + for key in ('vendorid', 'modelnumberid'): + if key in data: + setattr(d, key, data[key] or None) db.session.commit() return success_response(d.to_dict(), message='Driver updated') diff --git a/plugins/printers/frontend/views/PrinterDriversList.vue b/plugins/printers/frontend/views/PrinterDriversList.vue index 64355636..f7598fc5 100644 --- a/plugins/printers/frontend/views/PrinterDriversList.vue +++ b/plugins/printers/frontend/views/PrinterDriversList.vue @@ -61,6 +61,26 @@ +
+ + +
+
+ + +