fuck this shit

This commit is contained in:
cupcakearmy 2020-01-01 20:30:18 +01:00
parent 36b8147ddd
commit 9acc7f721f
2 changed files with 133 additions and 1 deletions

2
.gitignore vendored
View File

@ -5,7 +5,7 @@ __pycache__
# Pypi
build
dist
tumbo.*
tumbo.egg-info
# Editors
.vscode

132
tumbo/tumbo.py Normal file
View File

@ -0,0 +1,132 @@
import os
import random
import subprocess
from itertools import product
from multiprocessing import Pool, cpu_count
from typing import Optional
from termcolor import colored
from tumbo.utils import buffer_to_string, resolve_path, compile_string
def exec(command, *args, **kwargs):
output = subprocess.run(command, *args, capture_output=True, **kwargs)
if output.returncode is not 0:
raise Exception(buffer_to_string(output.stderr))
return buffer_to_string(output.stdout)
def exec_multiple(commands, *args, show=True, **kwargs):
try:
for command in commands:
print(colored(' '.join(command), 'blue', attrs=['bold']))
result = exec(command, *args, **kwargs)
if show:
print(result + '\n')
except Exception as e:
print(colored(e, 'red'))
def build_push_run(rendered, name, context, push, run, show=False):
try:
# Create a tmp dockerfile to work with
hash = resolve_path(context, str(random.getrandbits(128)))
if not os.access('.', os.W_OK):
print(colored('Cannot write to directory', 'red'))
return
if os.path.isfile(hash):
print(colored(f'File {hash} already exitsts.', 'red'))
return
with open(hash, 'w') as f:
f.write(rendered)
commands = [['docker', 'build', '-f', hash, '-t', name, '.']]
if (push):
commands.append(['docker', 'push', name])
if (run):
commands.append(['docker', 'run', '--rm', name])
exec_multiple(commands, cwd=context, show=show)
finally:
# Delete the tmp file
if os.path.exists(hash):
os.remove(hash)
def process_queue(queue, context, parallel, push, run):
queue = [
(rendered, tag, context, push, run, True)
for rendered, tag in queue
]
if parallel:
thread_count = parallel if type(parallel) is int else cpu_count()
with Pool(thread_count) as pool:
pool.starmap(build_push_run, queue)
else:
for item in queue:
build_push_run(*item)
def compile_templates(variables, recipe, tag, context, show=True):
queue = []
for item in product(*variables.values()):
zipped_variables = dict(zip(variables.keys(), item))
path = compile_string(recipe, zipped_variables)
if tag:
name = compile_string(tag, zipped_variables)
else:
# If no tag is provided construct one from all variables to avoid any duplicated tags
all_values_as_strings = map(str, zipped_variables.values())
name = '-'.join(all_values_as_strings)
name = name.lower() # Docker tags must be lower case
with open(resolve_path(context, path), 'r') as f:
rendered = compile_string(f.read(), zipped_variables)
queue.append((rendered, name))
if show:
print(
'\n' +
colored('Variation:', 'green') + f'\t{str(zipped_variables)}\n' +
colored('Recipe:', 'green') + f'\t\t{path}\n' +
colored('Tag:', 'green') + f'\t\t{name}\n'
)
return queue
def login_if_required(registry) -> Optional[str]:
if registry:
host = registry.get('host')
username = registry.get('username')
password = registry.get('password')
if not host:
raise Exception(colored('No host set for registry', 'red'))
cmd = ['docker', 'login']
if username or password:
if not username or not password:
raise Exception(colored('Username or password not set', 'red'))
# TODO: use stdin
cmd += ['-u', username, '-p', password]
try:
out = exec(cmd + [host])
print(colored(out + '\n', 'green'))
return host
except Exception as e:
print(colored('Could not log in, check your username', 'red'))
return None
return None