97 lines
3.9 KiB
Markdown
97 lines
3.9 KiB
Markdown
---
|
|
phase: 05-package-export
|
|
plan: "01"
|
|
subsystem: api/packages
|
|
tags: [fastapi, zip, intunewin, package-export, tdd]
|
|
dependency_graph:
|
|
requires:
|
|
- imptune/generators/script_generator.py (render_install, render_uninstall, render_detect)
|
|
- imptune/generators/intunewin_builder.py (build_intunewin)
|
|
- imptune/api/scripts.py (_get_printer_and_driver pattern)
|
|
- imptune/db/models.py (Printer, Driver ORM)
|
|
- imptune/config.py (DRIVERS_DIR)
|
|
provides:
|
|
- GET /printers/{id}/packages/ninja (NinjaRMM ZIP download)
|
|
- GET /printers/{id}/packages/intunewin (.intunewin download)
|
|
affects:
|
|
- imptune/main.py (router registration)
|
|
tech_stack:
|
|
added: []
|
|
patterns:
|
|
- In-memory ZIP assembly with io.BytesIO + zipfile.ZipFile
|
|
- TemporaryDirectory context manager for auto-cleanup of intunewin build artifacts
|
|
- Driver ZIP existence validation before processing
|
|
key_files:
|
|
created:
|
|
- imptune/api/packages.py
|
|
- tests/test_packages.py
|
|
modified:
|
|
- imptune/main.py
|
|
decisions:
|
|
- _get_printer_and_driver() copied (not imported) from scripts.py for module self-containment
|
|
- NinjaRMM ZIP uses DEFLATE compression with {printer_name}/install.ps1 + {printer_name}/drivers/* structure
|
|
- intunewin endpoint uses TemporaryDirectory for auto-cleanup of tmp build files (no manual cleanup needed)
|
|
- Driver ZIP file existence validated on disk before building package (422 if missing)
|
|
metrics:
|
|
duration: "~2 min"
|
|
completed_date: "2026-04-10"
|
|
tasks_completed: 1
|
|
files_modified: 3
|
|
requirements-completed: [PKG-01, PKG-02, PKG-03]
|
|
---
|
|
|
|
# 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`:
|
|
|
|
1. **`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)`
|
|
|
|
2. **`GET /printers/{id}/packages/intunewin`** — Returns a `.intunewin` file (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
|
|
|
|
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 |
|
|
|
|
## Self-Check: PASSED
|
|
|
|
- FOUND: imptune/api/packages.py
|
|
- FOUND: tests/test_packages.py
|
|
- FOUND: imptune/main.py (modified)
|
|
- FOUND commit a31c71e (RED tests)
|
|
- FOUND commit dd6cedf (GREEN implementation)
|