Files
Ansible/scripts/addons/webgui/tests/evidence_fixtures.py
T
2026-09-22 19:23:17 +02:00

69 lines
4.1 KiB
Python

"""Synthetic fixture data only; no controller inventory or real report observations."""
from pathlib import Path
import json,os,time,uuid
from ruamel.yaml import YAML
from aim_webgui.core.protocol import COUNTS
def declared(name='host_capabilities_v1',scope='per_host'):
source=Path(os.environ['AIM_TEST_CORE_ROOT'])/'playbooks/schemas'/f'{name}.yml'
schema=YAML(typ='safe').load(source.read_text())
return {'protocol':'aim_output_v1','schema':name,'scope':scope,'required':True,'sensitivity':'safe',
'max_bytes_per_host':1048576,'data_schema':schema}
def sample(schema):
t=schema['type']
if isinstance(t,list):t='null' if 'null' in t else t[0]
if 'enum' in schema:return schema['enum'][0]
if t=='object':return {k:sample(v) for k,v in schema['properties'].items()}
if t=='array':return []
if t=='boolean':return False
if t=='integer':return int(schema.get('minimum',0))
if t=='number':return float(schema.get('minimum',0))
if t=='null':return None
return 'synthetic'
def plan(declaration=None,hosts=None):
hosts=hosts or ['test01.example']
req={'customer':'example','playbook':'debug_detect_host_roles','hosts':hosts,'overrides':{},'check':False,
'key_mode':'none','become_password':False,'timeout_seconds':30,'progress_mode':'detail'}
return {'customer':'example','playbook':req['playbook'],'targets':hosts,'overrides':{},'result_contract':declaration,
'core_request':req,'core_version':'3.3.0rc8','core_api':'1.0','core_revision':'a'*64,'inventory_revision':'a'*64,
'credential_requirements':[],'authentication':{'mode':'inventory','key_mode':'none'}}
def result(declaration=None,hosts=None,*,availability='available',status='succeeded',report_data=None):
hosts=hosts or ['test01.example'];counts=dict.fromkeys(COUNTS,0);counts['ok']=3
report=None
if declaration is not None:
data=sample(declaration['data_schema']) if report_data is None else report_data
entry={'schema':declaration['schema'],'status':availability,'data':data if availability=='available' else None,'error':None}
report={'protocol':'aim_operation_result_v1','schema':declaration['schema'],'scope':declaration['scope'],
'required':True,'complete':availability=='available','check_mode':False,
'hosts':{h:dict(entry) for h in hosts} if declaration['scope']=='per_host' else {},
'global':dict(entry) if declaration['scope']=='global' else None}
return {'api_version':'1.0','run_id':'fixture-run','status':status,'stage':'completed' if status=='succeeded' else 'result_validation',
'exit_code':0,'remote_work_may_have_started':True,'counts':counts,
'error':None if status=='succeeded' else {'code':'operation_result_missing','message':'Required report missing','stage':'result_validation'},
'target_summary':{'schema':'target_outcome_summary_v1','requested':len(hosts),'accounted':len(hosts),
'successful':len(hosts),'failed':0,'unreachable':0,'not_started':0,'indeterminate':0,'complete':True},
'targets':[{'host':h,'outcome':'successful','counts':dict(counts)} for h in hosts],'operation_result':report}
def job(auth,owner,p=None,*,status='running'):
ident=uuid.uuid4().hex;p=p or plan()
with auth.store.transaction() as db:
db.execute('''INSERT INTO jobs(id,owner_id,plan,mode,status,scheduled_at,created_at) VALUES(?,?,?,?,?,?,?)''',
(ident,owner,json.dumps(p),'apply',status,int(time.time()),int(time.time())))
return ident
def ev(seq,kind='task_started',**extra):
data={'event_version':'1.0','run_id':'fixture-run','sequence':seq,'timestamp':'2026-09-20T10:00:00Z','kind':kind}
if kind=='task_started':data.update(play_id='p1',task_id='t'+str(seq),label='Synthetic task '+str(seq),label_redacted=False,handler=False)
if kind=='host_result':data.update(play_id='p1',task_id='t1',host='test01.example',host_redacted=False,status='ok',changed=False,ignored=False,details_redacted=False,error=None)
if kind=='stage':data['stage']='execution'
data.update(extra);return data