Display role vocabulary, migration commit fix, stale enforcement reports
This commit is contained in:
@@ -227,3 +227,39 @@ def test_report_without_a_subtype_stores_none(db):
|
||||
stored = ManifestEnforcementReport.query.filter_by(
|
||||
hostname='WJPC77', iscurrent=True).one()
|
||||
assert stored.subtype is None
|
||||
|
||||
|
||||
def test_reported_subtype_is_normalised_to_the_role_vocabulary(db):
|
||||
"""display-type.txt is hand-edited, so its casing drifts across the fleet.
|
||||
|
||||
Normalising on the way in keeps the fleet table reading one vocabulary
|
||||
instead of whatever each kiosk happened to be typed as.
|
||||
"""
|
||||
from plugins.geenforce.service import record_enforcement_report
|
||||
|
||||
for index, reported in enumerate(('lobby', 'LOBBY', ' Lobby ')):
|
||||
host = f'WJKIOSKCASE{index}'
|
||||
record_enforcement_report({'hostname': host,
|
||||
'scopename': 'gea-shopfloor-display',
|
||||
'subtype': reported, 'counts': {}})
|
||||
db.session.flush()
|
||||
stored = ManifestEnforcementReport.query.filter_by(
|
||||
hostname=host, iscurrent=True).one()
|
||||
assert stored.subtype == 'Lobby', reported
|
||||
|
||||
|
||||
def test_reported_subtype_keeps_an_unknown_value_verbatim(db):
|
||||
"""An unrecognised subtype is a typo on a kiosk or a role nobody declared.
|
||||
|
||||
Both are worth SEEING in the fleet table, so the value is stored as sent
|
||||
rather than blanked or guessed at.
|
||||
"""
|
||||
from plugins.geenforce.service import record_enforcement_report
|
||||
|
||||
record_enforcement_report({'hostname': 'WJKIOSKODD', 'scopename': 'gea-shopfloor-display',
|
||||
'subtype': 'Lobbby', 'counts': {}})
|
||||
db.session.flush()
|
||||
|
||||
stored = ManifestEnforcementReport.query.filter_by(
|
||||
hostname='WJKIOSKODD', iscurrent=True).one()
|
||||
assert stored.subtype == 'Lobbby'
|
||||
|
||||
@@ -185,3 +185,103 @@ def test_report_missing_hostname_rejected(client, db, app, auth_headers):
|
||||
resp = client.post('/api/geenforce/report', json={'scopename': 'x'},
|
||||
headers={'X-API-Key': secret})
|
||||
assert resp.status_code == 400
|
||||
|
||||
|
||||
# -- going quiet ------------------------------------------------------------
|
||||
#
|
||||
# A report records how one cycle went; nothing ages it. A PC switched off after
|
||||
# a clean run therefore kept 'ok' indefinitely and read as healthy - which is
|
||||
# how a machine offline for over a day still showed 'ok'.
|
||||
|
||||
def _age_report(db, hostname, minutes):
|
||||
"""Push a stored report's server-side receivedat back in time."""
|
||||
from datetime import timedelta
|
||||
from plugins.geenforce.models import ManifestEnforcementReport
|
||||
from plugins.geenforce.service import _utcnow
|
||||
(ManifestEnforcementReport.query
|
||||
.filter_by(hostname=hostname, iscurrent=True)
|
||||
.update({'receivedat': _utcnow() - timedelta(minutes=minutes)}))
|
||||
db.session.commit()
|
||||
|
||||
|
||||
def _post_clean_report(client, secret, hostname):
|
||||
return client.post('/api/geenforce/report', json={
|
||||
'hostname': hostname, 'scopename': 'gea-shopfloor-cmm',
|
||||
'appliedversion': 1, 'enforcerversion': '2.6',
|
||||
'counts': {'installed': 1, 'skipped': 0, 'failed': 0, 'filtered': 0},
|
||||
'results': [{'name': 'Alpha', 'action': 'installed'}],
|
||||
}, headers={'X-API-Key': secret})
|
||||
|
||||
|
||||
def test_a_pc_reporting_now_is_not_stale(client, db, app, auth_headers):
|
||||
_seed_and_publish(app)
|
||||
secret = _token(client, auth_headers, ['geenforce.report'])
|
||||
_post_clean_report(client, secret, 'WJCMM01')
|
||||
|
||||
row = client.get('/api/geenforce/reports',
|
||||
headers=auth_headers).get_json()['data'][0]
|
||||
assert row['status'] == 'ok'
|
||||
assert row['isstale'] is False
|
||||
assert row['staleafterminutes'] == 30
|
||||
|
||||
|
||||
def test_a_pc_that_stopped_reporting_goes_stale(client, db, app, auth_headers):
|
||||
_seed_and_publish(app)
|
||||
secret = _token(client, auth_headers, ['geenforce.report'])
|
||||
_post_clean_report(client, secret, 'WJCMM01')
|
||||
_age_report(db, 'WJCMM01', minutes=60 * 26) # offline over a day
|
||||
|
||||
row = client.get('/api/geenforce/reports',
|
||||
headers=auth_headers).get_json()['data'][0]
|
||||
assert row['isstale'] is True
|
||||
# The REPORTED status is left alone - it is still a true record of the last
|
||||
# cycle, and the UI shows it in the tooltip behind the stale badge.
|
||||
assert row['status'] == 'ok'
|
||||
|
||||
|
||||
def test_stale_boundary_is_the_configured_threshold(client, db, app, auth_headers):
|
||||
_seed_and_publish(app)
|
||||
secret = _token(client, auth_headers, ['geenforce.report'])
|
||||
_post_clean_report(client, secret, 'WJCMM01')
|
||||
|
||||
_age_report(db, 'WJCMM01', minutes=29)
|
||||
row = client.get('/api/geenforce/reports',
|
||||
headers=auth_headers).get_json()['data'][0]
|
||||
assert row['isstale'] is False, 'inside the window is not stale'
|
||||
|
||||
_age_report(db, 'WJCMM01', minutes=31)
|
||||
row = client.get('/api/geenforce/reports',
|
||||
headers=auth_headers).get_json()['data'][0]
|
||||
assert row['isstale'] is True, 'past the window is stale'
|
||||
|
||||
|
||||
def test_stale_threshold_is_a_setting(client, db, app, auth_headers):
|
||||
from shopdb.api import Setting
|
||||
_seed_and_publish(app)
|
||||
secret = _token(client, auth_headers, ['geenforce.report'])
|
||||
_post_clean_report(client, secret, 'WJCMM01')
|
||||
_age_report(db, 'WJCMM01', minutes=45)
|
||||
|
||||
Setting.set('geenforce_reportstaleminutes', '120', valuetype='integer',
|
||||
category='geenforce')
|
||||
db.session.commit()
|
||||
row = client.get('/api/geenforce/reports',
|
||||
headers=auth_headers).get_json()['data'][0]
|
||||
assert row['isstale'] is False
|
||||
assert row['staleafterminutes'] == 120
|
||||
|
||||
|
||||
def test_zero_disables_the_stale_check(client, db, app, auth_headers):
|
||||
from shopdb.api import Setting
|
||||
_seed_and_publish(app)
|
||||
secret = _token(client, auth_headers, ['geenforce.report'])
|
||||
_post_clean_report(client, secret, 'WJCMM01')
|
||||
_age_report(db, 'WJCMM01', minutes=60 * 24 * 7)
|
||||
|
||||
Setting.set('geenforce_reportstaleminutes', '0', valuetype='integer',
|
||||
category='geenforce')
|
||||
db.session.commit()
|
||||
row = client.get('/api/geenforce/reports',
|
||||
headers=auth_headers).get_json()['data'][0]
|
||||
assert row['isstale'] is False
|
||||
assert row['staleafterminutes'] == 0
|
||||
|
||||
Reference in New Issue
Block a user