Fetch log path template from secret
This commit is contained in:
Родитель
f35966f4a9
Коммит
58b7c35769
2
setup.py
2
setup.py
|
@ -2,7 +2,7 @@
|
|||
|
||||
from setuptools import setup
|
||||
|
||||
VERSION = "0.8.1"
|
||||
VERSION = "0.9.0"
|
||||
|
||||
CLASSIFIERS = [
|
||||
'Development Status :: 4 - Beta',
|
||||
|
|
|
@ -23,6 +23,8 @@ IS_WINDOWS = sys.platform.lower() in ['windows', 'win32']
|
|||
|
||||
coloredlogs.install(level=os.environ.get('A01_DEBUG', 'ERROR'))
|
||||
|
||||
NAMESPACE = 'az'
|
||||
|
||||
|
||||
def get_logger(name: str) -> logging.Logger:
|
||||
return logging.getLogger(name)
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
import json
|
||||
import datetime
|
||||
import base64
|
||||
from typing import List, Tuple, Generator
|
||||
|
||||
import colorama
|
||||
from requests import HTTPError
|
||||
from kubernetes import config as kube_config
|
||||
from kubernetes import client as kube_client
|
||||
|
||||
from a01.communication import session
|
||||
from a01.common import get_logger, A01Config
|
||||
from a01.common import get_logger, A01Config, LOG_FILE, NAMESPACE
|
||||
|
||||
|
||||
class Run(object):
|
||||
|
@ -29,6 +32,19 @@ class Run(object):
|
|||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def get(cls, run_id: str) -> 'Run':
|
||||
try:
|
||||
resp = session.get(f'{cls.endpoint_uri()}/run/{run_id}')
|
||||
resp.raise_for_status()
|
||||
return Run.from_dict(resp.json())
|
||||
except HTTPError:
|
||||
cls.logger.debug('HttpError', exc_info=True)
|
||||
raise ValueError('Failed to create run in the task store.')
|
||||
except (json.JSONDecodeError, TypeError):
|
||||
cls.logger.debug('JsonError', exc_info=True)
|
||||
raise ValueError('Failed to deserialize the response content.')
|
||||
|
||||
def post(self) -> str:
|
||||
try:
|
||||
resp = session.post(f'{self.endpoint_uri()}/run', json=self.to_dict())
|
||||
|
@ -40,6 +56,16 @@ class Run(object):
|
|||
self.logger.debug('JsonError', exc_info=True)
|
||||
raise ValueError('Failed to deserialize the response content.')
|
||||
|
||||
def get_log_path_template(self) -> str:
|
||||
run_secret_name = self.details.get('secret', None)
|
||||
if run_secret_name:
|
||||
kube_config.load_kube_config()
|
||||
secret = kube_client.CoreV1Api().read_namespaced_secret(name=run_secret_name, namespace=NAMESPACE)
|
||||
secret_data = secret.data.get('log.path.template', None)
|
||||
if secret_data:
|
||||
return base64.b64decode(secret_data).decode('utf-8')
|
||||
return LOG_FILE
|
||||
|
||||
@staticmethod
|
||||
def from_dict(data: dict) -> 'Run':
|
||||
result = Run(name=data['name'], settings=data['settings'], details=data['details'])
|
||||
|
|
|
@ -4,7 +4,7 @@ from typing import Tuple, Generator
|
|||
|
||||
import requests
|
||||
|
||||
from a01.common import get_logger, A01Config, LOG_FILE
|
||||
from a01.common import get_logger, A01Config
|
||||
from a01.communication import session
|
||||
|
||||
|
||||
|
@ -38,10 +38,6 @@ class Task(object): # pylint: disable=too-many-instance-attributes
|
|||
cls.logger.debug('JsonError', exc_info=True)
|
||||
raise ValueError('Fail to parse the runs data.')
|
||||
|
||||
@property
|
||||
def log_path(self) -> str:
|
||||
return LOG_FILE.format(f'{self.run_id}/task_{self.id}.log')
|
||||
|
||||
def to_dict(self) -> dict:
|
||||
result = {
|
||||
'name': self.name,
|
||||
|
@ -63,8 +59,9 @@ class Task(object): # pylint: disable=too-many-instance-attributes
|
|||
|
||||
return result
|
||||
|
||||
def get_log_content(self) -> Generator[str, None, None]:
|
||||
for index, line in enumerate(requests.get(self.log_path).content.decode('utf-8').split('\n')):
|
||||
def get_log_content(self, log_path_template: str) -> Generator[str, None, None]:
|
||||
log_path = log_path_template.format(f'{self.run_id}/task_{self.id}.log')
|
||||
for index, line in enumerate(requests.get(log_path).content.decode('utf-8').split('\n')):
|
||||
yield '>', f' {index}\t{line}'
|
||||
|
||||
def get_table_view(self) -> Tuple[str, ...]:
|
||||
|
@ -75,8 +72,8 @@ class Task(object): # pylint: disable=too-many-instance-attributes
|
|||
def get_table_header() -> Tuple[str, ...]:
|
||||
return 'Id', 'Name', 'Status', 'Result', 'Agent', 'Duration(ms)'
|
||||
|
||||
def download_recording(self, az_mode: bool) -> None:
|
||||
recording_path = LOG_FILE.format(f'{self.run_id}/recording_{self.id}.yaml')
|
||||
def download_recording(self, log_path_template: str, az_mode: bool) -> None:
|
||||
recording_path = log_path_template.format(f'{self.run_id}/recording_{self.id}.yaml')
|
||||
resp = requests.get(recording_path)
|
||||
if resp.status_code != 200:
|
||||
return
|
||||
|
|
|
@ -19,8 +19,6 @@ from a01.docker import DroidImage
|
|||
|
||||
logger = get_logger(__name__) # pylint: disable=invalid-name
|
||||
|
||||
NAMESPACE = 'az'
|
||||
|
||||
|
||||
@cmd('get runs', desc='Retrieve the runs.')
|
||||
def get_runs() -> None:
|
||||
|
@ -50,10 +48,16 @@ def get_run(run_id: str, log: bool = False, recording: bool = False, recording_a
|
|||
output_in_table(tasks.get_table_view(failed=not show_all), headers=tasks.get_table_header())
|
||||
output_in_table(tasks.get_summary(), tablefmt='plain')
|
||||
|
||||
log_path_template = None
|
||||
if log or recording:
|
||||
run = a01.models.Run.get(run_id=run_id)
|
||||
log_path_template = run.get_log_path_template()
|
||||
|
||||
if log:
|
||||
for failure in tasks.get_failed_tasks():
|
||||
output_in_table(zip_longest(failure.get_table_header(), failure.get_table_view()), tablefmt='plain')
|
||||
output_in_table(failure.get_log_content(), tablefmt='plain', foreground_color=colorama.Fore.CYAN)
|
||||
output_in_table(failure.get_log_content(log_path_template), tablefmt='plain',
|
||||
foreground_color=colorama.Fore.CYAN)
|
||||
|
||||
output_in_table(tasks.get_summary(), tablefmt='plain')
|
||||
|
||||
|
@ -61,7 +65,7 @@ def get_run(run_id: str, log: bool = False, recording: bool = False, recording_a
|
|||
print()
|
||||
print('Download recordings ...')
|
||||
for task in tasks.tasks:
|
||||
task.download_recording(recording_az_mode)
|
||||
task.download_recording(log_path_template, recording_az_mode)
|
||||
except ValueError as err:
|
||||
logger.error(err)
|
||||
sys.exit(1)
|
||||
|
|
|
@ -22,12 +22,18 @@ def get_task(ids: [str], log: bool = False, recording: bool = False, recording_a
|
|||
task = a01.models.Task.get(task_id=task_id)
|
||||
output_in_table(zip_longest(task.get_table_header(), task.get_table_view()), tablefmt='plain')
|
||||
|
||||
log_path_template = None
|
||||
if log or recording:
|
||||
run = a01.models.Run.get(run_id=task.run_id)
|
||||
log_path_template = run.get_log_path_template()
|
||||
|
||||
if log:
|
||||
print()
|
||||
output_in_table(task.get_log_content(), tablefmt='plain', foreground_color=colorama.Fore.CYAN)
|
||||
output_in_table(task.get_log_content(log_path_template), tablefmt='plain',
|
||||
foreground_color=colorama.Fore.CYAN)
|
||||
|
||||
if recording:
|
||||
print()
|
||||
task.download_recording(recording_az_mode)
|
||||
task.download_recording(log_path_template, recording_az_mode)
|
||||
|
||||
print()
|
||||
|
|
Загрузка…
Ссылка в новой задаче