- Update printer_detail() to pass install_cmd, uninstall_cmd, has_driver, has_icon to template - Rewrite printer_detail.html with Intune Commands, Export, and Icon sections - Show command strings with Alpine.js copy-to-clipboard buttons (install-cmd, uninstall-cmd) - Show NinjaRMM ZIP and .intunewin download links when driver assigned - Add HTMX icon upload form with #icon-status swap target - Remove disabled placeholder Regenerate Package button - Add TestCommandPreview class (4 tests) to test_packages.py - All 94 tests pass
3.9 KiB
phase, plan, subsystem, tags, dependency_graph, tech_stack, key_files, decisions, metrics
| phase | plan | subsystem | tags | dependency_graph | tech_stack | key_files | decisions | metrics | |||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 05-package-export | 01 | api/packages |
|
|
|
|
|
|
Phase 5 Plan 1: Package Export Endpoints Summary
One-liner: NinjaRMM ZIP and .intunewin package export endpoints using in-memory ZIP assembly and Python-native intunewin build.
What Was Built
Two GET endpoints on imptune/api/packages.py:
-
GET /printers/{id}/packages/ninja— Returns a ZIP file (application/zip) with:{safe_name}/install.ps1— rendered PowerShell install script{safe_name}/drivers/*— all driver files extracted from the driver ZIP on disk- Built entirely in-memory with
io.BytesIO+zipfile.ZipFile(ZIP_DEFLATED)
-
GET /printers/{id}/packages/intunewin— Returns a.intunewinfile (application/octet-stream) with:- Writes install.ps1, uninstall.ps1, detect.ps1 into a
TemporaryDirectory - Extracts driver ZIP into
tmpdir/drivers/ - Calls
build_intunewin(tmpdir, "install.ps1", output_path)— no subprocess calls - Reads bytes and returns as binary Response
- Writes install.ps1, uninstall.ps1, detect.ps1 into a
Both endpoints share _get_printer_and_driver() helper (404 for missing printer, 422 for no/invalid driver) and validate the driver ZIP file exists on disk (422 if missing).
Router registered in imptune/main.py after scripts.router.
Tests
9 new tests in tests/test_packages.py:
TestNinjaDownload: 5 tests (zip response, install.ps1 in zip, driver files in zip, 404, 422)TestIntunewinDownload: 4 tests (intunewin response, valid outer ZIP structure, 404, 422)
Full suite result: 84 passed (excluding pre-existing icon upload failures in test_icon_upload.py which existed before this plan).
Deviations from Plan
None — plan executed exactly as written.
Pre-existing Issues (Out of Scope)
tests/test_icon_upload.py has 5 failing tests (/printers/{id}/icon returns 404). These failures existed before this plan was executed and are unrelated to package export. Logged for future attention.
Commits
| Hash | Type | Description |
|---|---|---|
a31c71e |
test | add failing tests for NinjaRMM ZIP and intunewin endpoints |
dd6cedf |
feat | implement NinjaRMM ZIP and intunewin package export endpoints |