mirror of
https://github.com/trailofbits/algo.git
synced 2025-09-06 20:13:11 +02:00
Switched to ansible_runner API
This commit is contained in:
parent
1668f6a904
commit
23f8332319
2 changed files with 55 additions and 36 deletions
|
@ -1,2 +1,3 @@
|
||||||
aiohttp==3.6.2
|
aiohttp==3.8.1
|
||||||
|
ansible-runner==2.2.1
|
||||||
boto3
|
boto3
|
|
@ -10,11 +10,10 @@ import sys
|
||||||
from os.path import join, dirname, expanduser
|
from os.path import join, dirname, expanduser
|
||||||
from urllib.parse import quote, urlencode
|
from urllib.parse import quote, urlencode
|
||||||
|
|
||||||
|
import ansible_runner
|
||||||
import yaml
|
import yaml
|
||||||
from aiohttp import web, ClientSession
|
from aiohttp import web, ClientSession
|
||||||
|
|
||||||
from playbook import PlaybookCLI
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import boto3
|
import boto3
|
||||||
|
|
||||||
|
@ -47,6 +46,7 @@ except ImportError:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from cs import AIOCloudStack, CloudStackApiException
|
from cs import AIOCloudStack, CloudStackApiException
|
||||||
|
|
||||||
HAS_CS_LIBRARIES = True
|
HAS_CS_LIBRARIES = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_CS_LIBRARIES = False
|
HAS_CS_LIBRARIES = False
|
||||||
|
@ -58,12 +58,49 @@ task_future = None
|
||||||
task_program = ''
|
task_program = ''
|
||||||
|
|
||||||
|
|
||||||
def run_playbook(data):
|
class Status:
|
||||||
global task_program
|
RUNNING = 'run'
|
||||||
extra_vars = ' '.join(['{0}={1}'.format(key, data[key])
|
ERROR = 'error'
|
||||||
for key in data.keys()])
|
CANCELLED = 'cancelled'
|
||||||
task_program = ['ansible-playbook', 'main.yml', '--extra-vars', extra_vars]
|
DONE = 'done'
|
||||||
return PlaybookCLI(task_program).run()
|
NEW = None
|
||||||
|
|
||||||
|
|
||||||
|
class Playbook:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.status = Status.NEW
|
||||||
|
self.want_cancel = False
|
||||||
|
self.events = []
|
||||||
|
self._runner = None
|
||||||
|
|
||||||
|
def event_handler(self, data: dict) -> None:
|
||||||
|
self.events.append(data)
|
||||||
|
|
||||||
|
def cancel_handler(self) -> bool:
|
||||||
|
if self.want_cancel:
|
||||||
|
self.status = Status.CANCELLED
|
||||||
|
return self.want_cancel
|
||||||
|
|
||||||
|
def cancel(self) -> None:
|
||||||
|
self.want_cancel = True
|
||||||
|
|
||||||
|
def run(self, extra_vars: dict) -> None:
|
||||||
|
self.want_cancel = False
|
||||||
|
self.status = Status.RUNNING
|
||||||
|
_, runner = ansible_runner.run_async(private_data_dir='.',
|
||||||
|
playbook='main.yml',
|
||||||
|
extravars=extra_vars,
|
||||||
|
cancel_callback=self.cancel_handler,
|
||||||
|
event_handler=self.event_handler)
|
||||||
|
self._runner = runner
|
||||||
|
|
||||||
|
|
||||||
|
playbook = Playbook()
|
||||||
|
|
||||||
|
|
||||||
|
def run_playbook(data: dict):
|
||||||
|
return playbook.run(data)
|
||||||
|
|
||||||
|
|
||||||
@routes.get('/')
|
@routes.get('/')
|
||||||
|
@ -73,43 +110,24 @@ async def handle_index(_):
|
||||||
|
|
||||||
|
|
||||||
@routes.get('/playbook')
|
@routes.get('/playbook')
|
||||||
async def playbook_get_handler(request):
|
async def playbook_get_handler(_):
|
||||||
if not task_future:
|
return web.json_response({
|
||||||
return web.json_response({'status': None})
|
'status': playbook.status,
|
||||||
|
'events': playbook.events,
|
||||||
if task_future.done():
|
})
|
||||||
try:
|
|
||||||
return web.json_response({'status': 'done', 'program': task_program, 'result': task_future.result()})
|
|
||||||
except ValueError as e:
|
|
||||||
return web.json_response({'status': 'error', 'program': task_program, 'result': str(e)})
|
|
||||||
elif task_future.cancelled():
|
|
||||||
return web.json_response({'status': 'cancelled', 'program': task_program})
|
|
||||||
else:
|
|
||||||
return web.json_response({'status': 'running', 'program': task_program})
|
|
||||||
|
|
||||||
|
|
||||||
@routes.post('/playbook')
|
@routes.post('/playbook')
|
||||||
async def playbook_post_handler(request):
|
async def playbook_post_handler(request):
|
||||||
global task_future
|
|
||||||
global pool
|
|
||||||
data = await request.json()
|
data = await request.json()
|
||||||
loop = asyncio.get_running_loop()
|
run_playbook(data)
|
||||||
|
|
||||||
pool = concurrent.futures.ThreadPoolExecutor()
|
|
||||||
task_future = loop.run_in_executor(pool, run_playbook, data)
|
|
||||||
return web.json_response({'ok': True})
|
return web.json_response({'ok': True})
|
||||||
|
|
||||||
|
|
||||||
@routes.delete('/playbook')
|
@routes.delete('/playbook')
|
||||||
async def playbook_delete_handler(_):
|
async def playbook_delete_handler(_):
|
||||||
global task_future
|
playbook.cancel()
|
||||||
if not task_future:
|
return web.json_response({'ok': True})
|
||||||
return web.json_response({'ok': False})
|
|
||||||
|
|
||||||
cancelled = task_future.cancel()
|
|
||||||
pool.shutdown(wait=False)
|
|
||||||
task_future = None
|
|
||||||
return web.json_response({'ok': cancelled})
|
|
||||||
|
|
||||||
|
|
||||||
@routes.get('/config')
|
@routes.get('/config')
|
||||||
|
|
Loading…
Add table
Reference in a new issue