aim-web2.1.0rc9
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import json
|
||||
import concurrent.futures
|
||||
import sqlite3
|
||||
import time
|
||||
from dataclasses import replace
|
||||
import pytest
|
||||
from aim_webgui.workflows import Workflows, presentation_status
|
||||
from aim_webgui.errors import WebError
|
||||
|
||||
|
||||
def reviewed(flow,admin,**kw):
|
||||
return flow.review(admin,'example','debug_test_connection',['test01.example'],{},**kw)
|
||||
|
||||
|
||||
|
||||
def test_partial_success_presentation_uses_core_target_summary():
|
||||
core={'target_summary':{'schema':'target_outcome_summary_v1','requested':25,'successful':24,'failed':0,'unreachable':1,'not_started':0,'indeterminate':0,'complete':True,'accounted':25}}
|
||||
assert presentation_status('failed',core)=='partially_succeeded'
|
||||
assert presentation_status('successful',core)=='successful'
|
||||
core['target_summary']['successful']=0;core['target_summary']['failed']=24
|
||||
assert presentation_status('failed',core)=='failed'
|
||||
|
||||
def test_one_run_without_saving(settings,admin):
|
||||
f=Workflows(settings);r=reviewed(f,admin)
|
||||
ident=f.queue_review(admin,r['review_id'],idempotency_key='OneRun1')
|
||||
assert f.job(admin,ident)['status']=='queued'
|
||||
assert f.plans(admin)==[]
|
||||
assert f.queue_review(admin,r['review_id'],idempotency_key='OneRun1')==ident
|
||||
with pytest.raises(WebError):f.queue_review(admin,r['review_id'],scheduled_at=int(time.time())+60,idempotency_key='OneRun1')
|
||||
|
||||
|
||||
def test_optional_plan_names_and_collision(settings,admin):
|
||||
f=Workflows(settings);r=reviewed(f,admin)
|
||||
a=f.save_review(admin,r['review_id'],'');b=f.save_review(admin,r['review_id'],'')
|
||||
assert a!=b and f.plan(admin,a)['name']!=f.plan(admin,b)['name']
|
||||
p=f.save_review(admin,r['review_id'],'My Plan')
|
||||
with pytest.raises(WebError) as e:f.save_review(admin,r['review_id'],' MY PLAN ')
|
||||
assert e.value.code=='plan_name_exists'
|
||||
assert f.plan(admin,p)['name']=='My Plan'
|
||||
assert len(f.plans(admin))==3
|
||||
|
||||
|
||||
def test_unicode_name_equivalence(settings,admin):
|
||||
f=Workflows(settings);r=reviewed(f,admin)
|
||||
f.save_review(admin,r['review_id'],'Plan A')
|
||||
with pytest.raises(WebError):f.save_review(admin,r['review_id'],'Plan \uff21')
|
||||
|
||||
|
||||
def test_concurrent_saves_do_not_overwrite(settings,admin):
|
||||
f=Workflows(settings);r=reviewed(f,admin)
|
||||
def save():
|
||||
try:return f.save_review(admin,r['review_id'],'concurrent')
|
||||
except WebError as e:return e.code
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=2) as ex:results=list(ex.map(lambda _:save(),range(2)))
|
||||
assert results.count('plan_name_exists')==1
|
||||
assert len(f.plans(admin))==1
|
||||
|
||||
|
||||
def test_stale_review_rejected(settings,admin,core_root):
|
||||
f=Workflows(settings);r=reviewed(f,admin)
|
||||
with (core_root/'inventories/example/hosts.yml').open('a') as file:file.write('# external edit\n')
|
||||
with pytest.raises(WebError) as e:f.queue_review(admin,r['review_id'],idempotency_key='fresh1')
|
||||
assert e.value.code=='plan_stale'
|
||||
|
||||
|
||||
def test_mode_and_authentication_bound_to_revision(settings,admin):
|
||||
f=Workflows(settings);r=reviewed(f,admin,check=False)
|
||||
ident=f.queue_review(admin,r['review_id'],idempotency_key='mode1')
|
||||
job=f.job(admin,ident)
|
||||
assert job['mode']=='apply' and job['plan']['core_request']['check'] is False
|
||||
assert job['plan']['authentication']['mode']=='inventory'
|
||||
|
||||
|
||||
def test_pending_approval_when_enabled(settings,admin):
|
||||
f=Workflows(replace(settings,execution_require_approval=True));r=reviewed(f,admin)
|
||||
ident=f.queue_review(admin,r['review_id'],idempotency_key='approval1')
|
||||
assert f.job(admin,ident)['status']=='pending'
|
||||
with pytest.raises(WebError):f.job_action(admin,ident,'approve')
|
||||
|
||||
|
||||
def test_core_opt_in_separate(settings,admin,core_root):
|
||||
config=core_root/'scripts/aim.yml';config.write_text(config.read_text().replace('execution_enabled: true','execution_enabled: false'))
|
||||
f=Workflows(settings);r=reviewed(f,admin)
|
||||
with pytest.raises(WebError) as e:f.queue_review(admin,r['review_id'],idempotency_key='disabled1')
|
||||
assert e.value.code=='core_execution_disabled'
|
||||
|
||||
|
||||
def test_retry_creates_fresh_job_and_bulk_delete_preserves_audit(settings,admin):
|
||||
f=Workflows(settings);r=reviewed(f,admin)
|
||||
one=f.queue_review(admin,r['review_id'],idempotency_key='retry1')
|
||||
with f.store.transaction() as db:db.execute("UPDATE jobs SET status='failed' WHERE id=?",(one,))
|
||||
two=f.retry_job(admin,one)
|
||||
assert two!=one and f.job(admin,two)['status']=='queued'
|
||||
with pytest.raises(WebError):f.delete_jobs(admin,[one,two])
|
||||
f.delete_jobs(admin,[one])
|
||||
with f.store.read() as db:assert db.execute("SELECT 1 FROM audit WHERE action='job-deleted'").fetchone()
|
||||
|
||||
|
||||
def test_legacy_plan_requires_fresh_review(settings,admin):
|
||||
f=Workflows(settings)
|
||||
with f.store.transaction() as db:
|
||||
db.execute('INSERT INTO plans(id,owner_id,name,customer,playbook,payload,created_at) VALUES(?,?,?,?,?,?,?)',('a'*32,admin,'legacy','example','debug_test_connection',json.dumps({'customer':'example','playbook':'debug_test_connection','targets':['test01.example'],'overrides':{}}),0))
|
||||
assert f.plan(admin,'a'*32)['name']=='legacy'
|
||||
assert 'core_request' not in f.plan(admin,'a'*32)['payload']
|
||||
Reference in New Issue
Block a user