зеркало из
1
0
Форкнуть 0
This commit is contained in:
Troy Dai 2018-03-21 15:18:11 -07:00
Родитель acfe71d4fb
Коммит 12036ecc05
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 9608535492BEDAC8
7 изменённых файлов: 117 добавлений и 9 удалений

Просмотреть файл

@ -4,7 +4,6 @@ certifi==2017.11.5
chardet==3.0.4
colorama==0.3.9
coloredlogs==8.0
docker==3.0.0
humanfriendly==4.6
idna==2.6
isort==4.2.15
@ -21,4 +20,7 @@ kubernetes==4.0.0
websocket-client==0.40.0
wheel==0.30.0
kubernetes==4.0.0
docker==3.0.0
-e .

Просмотреть файл

@ -40,6 +40,8 @@ DEPENDENCIES = [
'colorama>=0.3.9',
'adal>=0.5.0',
'docker~=3.0.0',
'kubernetes~=4.0.0',
'docker~=3.0.0'
]
setup(

Просмотреть файл

@ -15,6 +15,7 @@ def main() -> None:
__import__('a01.images')
__import__('a01.config')
__import__('a01.auth')
__import__('a01.repo')
parser = setup_commands()
args = parser.parse_args()

Просмотреть файл

@ -32,6 +32,14 @@ class Run(object):
for k in to_delete:
del self.details[k]
@property
def image(self) -> str:
return self.settings['a01.reserved.imagename']
@property
def product(self) -> str:
return self.details['a01.reserved.product']
def to_dict(self) -> dict:
result = {
'name': self.name,

Просмотреть файл

@ -27,6 +27,10 @@ class Task(object): # pylint: disable=too-many-instance-attributes
def identifier(self) -> str:
return self.settings['classifier']['identifier']
@property
def command(self) -> str:
return self.settings['execution']['command']
@classmethod
def get(cls, task_id: str) -> 'Task':
try:

97
src/a01/repo.py Normal file
Просмотреть файл

@ -0,0 +1,97 @@
import sys
import base64
import yaml
import docker
import docker.errors
import requests
import colorama
from kubernetes import config as kube_config
from kubernetes import client as kube_client
from tabulate import tabulate
from a01.models import Task, Run
from a01.cli import cmd, arg
# pylint: disable=too-many-statements
@cmd('repo task', desc="Rerun a task locally")
@arg('task_id', positional=True)
@arg('live', help='Rerun in live env')
@arg('interactive', option=['-i', '--interactive'], help='Start the container in interactive mode')
@arg('shell', help='The shell to use for interactive mode')
@arg('mode', help='Need a mode')
def reproduce_task(task_id: str, live: bool = False, interactive: bool = False, shell: str = '/bin/bash',
mode: str = None) -> None:
task = Task.get(task_id)
run = Run.get(task.run_id)
summary = {
'name': task.name,
'image': run.image,
'command': task.command,
}
print('\nBrief\n')
print(tabulate(summary.items(), tablefmt='plain'))
print()
try:
client = docker.from_env()
if not client.images.list(run.image):
print('Pulling the test image ...')
client.images.pull(*(run.image.split(':')))
else:
print(f'Image {run.image} exists locally.')
print('Retrieve metadata')
metadata = client.containers.run(run.image, 'cat /app/metadata.yml', remove=True)
metadata = yaml.load(metadata)
print('Get secrets from the Kubernetes cluster')
kube_config.load_kube_config()
kapi = kube_client.CoreV1Api()
secret = kapi.read_namespaced_secret(run.product, 'a01-prod')
repo_environment_variables = {}
for env in metadata['environments']:
if env['type'] == 'secret':
value = secret.data[env['value']]
value = base64.b64decode(value).decode('utf-8')
repo_environment_variables[env["name"]] = value
elif env['type'] == 'argument-switch-live':
if live:
repo_environment_variables[env["name"]] = env["value"]
elif env['type'] == 'argument-value-mode':
if mode:
repo_environment_variables[env['name']] = mode
print('Environment:')
print(tabulate(repo_environment_variables.items(), tablefmt='plain') + '\n')
if interactive:
print('Start the container in interactive mode ...\n')
cont = client.containers.run(run.image, shell, environment=repo_environment_variables, auto_remove=True,
detach=True, tty=True, stdin_open=True)
print(f'\n\nRun following command to enter the container\'s shell:')
print(f'\n{colorama.Fore.YELLOW}docker attach {cont.name}{colorama.Fore.RESET}\n')
print(f'\nRun following command in the container to rerun the task:')
print(f'\n{colorama.Fore.YELLOW}{task.command}{colorama.Fore.RESET}\n\n')
else:
print('Run task in local container ...\n')
cont = client.containers.run(run.image, task.command, environment=repo_environment_variables, detach=True)
cont.wait()
print('\nRun finished ...\n')
print(colorama.Fore.LIGHTYELLOW_EX + cont.logs().decode('utf-8') + colorama.Fore.RESET)
cont.remove()
except requests.HTTPError:
print(f'Please login the docker container registry {run.image.split("/")[0]}')
sys.exit(1)

Просмотреть файл

@ -60,16 +60,10 @@ 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(log_path_template), tablefmt='plain',
foreground_color=colorama.Fore.CYAN)
output_in_table(failure.get_log_content(), tablefmt='plain', foreground_color=colorama.Fore.CYAN)
output_in_table(tasks.get_summary(), tablefmt='plain')
@ -77,7 +71,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(log_path_template, recording_az_mode)
task.download_recording(recording_az_mode)
if raw:
run = a01.models.Run.get(run_id=run_id)