Files
shopdb-flask/scripts/dev/seed_shared_applications.py
benjamin.baker 01734e5449 harden CSV import reconciliation and preserve saved model selections
Default fuzzy reconcile threshold to 0 and refuse merges when digit runs differ so numbered labels like Bay 311 never bind to Bay 310. Keep edit forms from clearing saved model fields when category filtering hides untyped rows. Includes in-progress computers policy and endpoints command feature work.
2026-08-28 09:29:09 -04:00

103 lines
3.4 KiB
Python

"""Seed the org's shared shopfloor applications (DEV ONLY).
Inserts the applications that ship as common across the organization so the
Configuration Policy builder has real apps to scope against and the software
inventory has canonical rows to match collected installs to. Each app records
its executable and (where relevant) its Windows service name in
applicationnotes, since the Application model has no dedicated process/service
column - these identifiers are what a generic service_*/process_* policy action
targets.
Shipped set:
* UDC - UDC.exe
* MTConnect - agent.exe process, "MTConnect UDC Agent" service
* eDNC - DncMain.exe process
Idempotent: matches on appname and updates in place, so re-running does not
duplicate. Marked installable so they appear in installable-app pickers.
DEV ONLY: lives under scripts/dev/ and must never be imported by application
code. Run inside the API container.
Usage (in the API container):
docker exec shopdb-flask-wilm-api-1 python scripts/dev/seed_shared_applications.py
docker exec shopdb-flask-wilm-api-1 python scripts/dev/seed_shared_applications.py --clear
"""
import argparse
import os
import sys
# Repo root on sys.path so `shopdb` imports when run as a script.
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
from shopdb import create_app # noqa: E402
from shopdb.api import db # noqa: E402
# appname -> seed fields. 'notes' captures the process image and service name so
# a generic policy action (params.target) has a canonical identifier to bind to.
SHARED_APPS = [
{
'appname': 'UDC',
'appdescription': 'Universal Data Collector',
'notes': 'process=UDC.exe',
},
{
'appname': 'MTConnect',
'appdescription': 'MTConnect UDC agent',
'notes': 'process=agent.exe; service=MTConnect UDC Agent',
},
{
'appname': 'eDNC',
'appdescription': 'eDNC distributed NC file transfer',
'notes': 'process=DncMain.exe',
},
]
def _seed(Application):
created = 0
updated = 0
for spec in SHARED_APPS:
app_row = Application.query.filter_by(appname=spec['appname']).first()
if app_row is None:
app_row = Application(appname=spec['appname'])
db.session.add(app_row)
created += 1
else:
updated += 1
app_row.appdescription = spec['appdescription']
app_row.applicationnotes = spec['notes']
app_row.isinstallable = True
db.session.commit()
print('Seeded shared applications: {} created, {} updated.'
.format(created, updated))
def _clear(Application):
names = [spec['appname'] for spec in SHARED_APPS]
removed = (Application.query
.filter(Application.appname.in_(names))
.delete(synchronize_session=False))
db.session.commit()
print('Removed {} shared application row(s).'.format(removed))
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--clear', action='store_true',
help='Remove the seeded shared applications.')
args = parser.parse_args()
app = create_app(os.environ.get('FLASK_ENV', 'production'))
with app.app_context():
from shopdb.api import Application
if args.clear:
_clear(Application)
else:
_seed(Application)
if __name__ == '__main__':
main()