WJ import loader: catalog + assets-hub stages (the machineid->assetid crosswalk)
Some checks failed
CI / backend (push) Successful in 1m39s
CI / naming (push) Successful in 1s
CI / frontend (push) Successful in 8s
CI / migrations-mysql (push) Failing after 8s

Adds the keystone stages to the reference loader.

catalog: seeds modeltypes (from classic machinetypes + category), the per-plugin
asset subtypes routed by machinetype (machines/network/measuringtool types),
computer subtypes (from pctype), the 5-row controllertypes vendor/model split,
and the models catalog - each with a persisted legacy->new crosswalk. Verified:
modeltypes 31, computertypes 12, models 118.

assets (the hub): fans classic machines out to the right endpoint by
machinetypeid (+ the pctype metrology override), applying the resolved
decisions - assetnumber = machinenumber else hostname, skip 9999, skip duplicate
machinenumbers, LocationOnly/printer/USB routed out. Persists the machineid ->
assetid crosswalk every downstream stage needs. Verified against a fresh scratch
target: 884 assets (computer 623, machine 68, network 58, measuringtool 135),
zero endpoint errors, idempotent re-run (stays 884). Skips: location 158, dup 69,
other 53, 9999 1.

Harness now runs each plugin's idempotent on_install so the AssetType rows exist
(a DB built with plugin upgrade-all instead of a fresh install lacks them, and
the create routes 500 without them). 409-resolve lookups page through per_page.

Remaining stages: communications (primary IP fold - source is the communications
table, not machines.ipaddress1), applications/installs, warranties, notifications,
KB, subnets/VLANs, usb, verify.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-07-13 11:37:11 -04:00
parent b11a6f26d8
commit 6c4bd20e01
2 changed files with 236 additions and 15 deletions

View File

@@ -94,6 +94,7 @@ class Harness:
self.appcontext.push()
self._silence_sql_logging()
self.client = self.app.test_client()
self._ensure_asset_types()
self.secret = self._mint_admin_pat()
default = os.path.join(os.path.dirname(__file__), 'idmap.json')
self.ids = IdMap(idmap_path or default)
@@ -104,6 +105,21 @@ class Harness:
import logging
logging.getLogger('sqlalchemy.engine').setLevel(logging.WARNING)
def _ensure_asset_types(self):
"""Register each plugin's AssetType + seeded subtypes. on_install (which
does this) is skipped when a DB is built with `flask plugin upgrade-all`
rather than a fresh `install`, so run it idempotently here - the create
routes 500 without the AssetType row."""
manager = self.app.extensions.get('plugin_manager')
if not manager:
return
for _name, plugin in manager.get_all_plugins().items():
try:
plugin.on_install(self.app)
except Exception:
pass
db.session.commit()
def _mint_admin_pat(self):
"""Create (or reuse) an admin user and an unscoped admin PAT. Unscoped
because import mode + role gates require full owner authority