Add up command, allow fine grain debug output
This commit is contained in:
parent
409b625309
commit
2e9a23eb5a
@ -40,7 +40,11 @@ class ConsoleScript(cli2.ConsoleScript):
|
|||||||
for name, script in self.podfile.pod.scripts.items():
|
for name, script in self.podfile.pod.scripts.items():
|
||||||
cb = self.podfile.pod.script(name)
|
cb = self.podfile.pod.script(name)
|
||||||
cb.__doc__ = inspect.getdoc(script) or script.doc
|
cb.__doc__ = inspect.getdoc(script) or script.doc
|
||||||
self[name] = cli2.Callable(name, cb)
|
self[name] = cli2.Callable(
|
||||||
|
name,
|
||||||
|
cb,
|
||||||
|
options=script.options,
|
||||||
|
)
|
||||||
return super().__call__(*args, **kwargs)
|
return super().__call__(*args, **kwargs)
|
||||||
|
|
||||||
def call(self, command):
|
def call(self, command):
|
||||||
|
|||||||
@ -4,16 +4,48 @@ import os
|
|||||||
|
|
||||||
from .build import Build
|
from .build import Build
|
||||||
from .container import Container
|
from .container import Container
|
||||||
|
from .exceptions import WrongResult
|
||||||
from .script import Script
|
from .script import Script
|
||||||
from .visitable import Visitable
|
from .visitable import Visitable
|
||||||
|
|
||||||
|
|
||||||
|
class Up(Script):
|
||||||
|
async def run(self, *args, **kwargs):
|
||||||
|
for key, value in kwargs.items():
|
||||||
|
setattr(self, key, value)
|
||||||
|
|
||||||
|
pod = kwargs.get('pod')
|
||||||
|
|
||||||
|
try:
|
||||||
|
pod.info = (await self.exec(
|
||||||
|
'podman', 'pod', 'inspect', pod.name
|
||||||
|
)).json
|
||||||
|
print(f'Pod {pod.name} ready')
|
||||||
|
except WrongResult:
|
||||||
|
print(f'Pod {pod.name} creating')
|
||||||
|
await self.exec(
|
||||||
|
'podman', 'pod', 'create', '--name', self.pod.name,
|
||||||
|
)
|
||||||
|
print(f'Pod {pod.name} created')
|
||||||
|
pod.info = (await self.exec(
|
||||||
|
'podman', 'pod', 'inspect', pod.name
|
||||||
|
)).json
|
||||||
|
|
||||||
|
return await super().run(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class Pod(Visitable):
|
class Pod(Visitable):
|
||||||
default_scripts = dict(
|
default_scripts = dict(
|
||||||
build=Build(),
|
build=Build(),
|
||||||
run=Script('run', 'Run a container command'),
|
run=Script('run', 'Run a container command'),
|
||||||
|
up=Up('up', 'Start the stack'),
|
||||||
|
test=Script('test', 'Run tests inside containers'),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return os.getenv('POD', os.getcwd().split('/')[-1])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def containers(self):
|
def containers(self):
|
||||||
return [i for i in self.visitors if type(i) == Container]
|
return [i for i in self.visitors if type(i) == Container]
|
||||||
@ -22,20 +54,6 @@ class Pod(Visitable):
|
|||||||
async def cb(*args, **kwargs):
|
async def cb(*args, **kwargs):
|
||||||
asyncio.events.get_event_loop()
|
asyncio.events.get_event_loop()
|
||||||
script = copy.deepcopy(self.scripts[name])
|
script = copy.deepcopy(self.scripts[name])
|
||||||
|
kwargs['pod'] = self
|
||||||
if args:
|
return await script.run(*args, **kwargs)
|
||||||
containers = [c for c in self.containers if c.name in args]
|
|
||||||
else:
|
|
||||||
containers = self.containers
|
|
||||||
|
|
||||||
procs = []
|
|
||||||
for container in containers:
|
|
||||||
procs.append(script(
|
|
||||||
container,
|
|
||||||
*args,
|
|
||||||
container=container,
|
|
||||||
pod=self,
|
|
||||||
**kwargs,
|
|
||||||
))
|
|
||||||
return await asyncio.gather(*procs)
|
|
||||||
return cb
|
return cb
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import importlib
|
import importlib
|
||||||
|
import os
|
||||||
|
|
||||||
from .container import Container
|
from .container import Container
|
||||||
from .pod import Pod
|
from .pod import Pod
|
||||||
@ -8,9 +9,14 @@ class Podfile:
|
|||||||
def __init__(self, pods, containers):
|
def __init__(self, pods, containers):
|
||||||
self.pods = pods
|
self.pods = pods
|
||||||
self.containers = containers
|
self.containers = containers
|
||||||
|
|
||||||
if not self.pods:
|
if not self.pods:
|
||||||
self.pods['pod'] = Pod(*containers.values())
|
self.pods['pod'] = Pod(*containers.values())
|
||||||
|
|
||||||
|
for pod in self.pods.values():
|
||||||
|
for container in pod.containers:
|
||||||
|
container.pod = pod
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pod(self):
|
def pod(self):
|
||||||
return self.pods['pod']
|
return self.pods['pod']
|
||||||
|
|||||||
@ -20,12 +20,16 @@ class PrefixStreamProtocol(asyncio.subprocess.SubprocessStreamProtocol):
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def pipe_data_received(self, fd, data):
|
def pipe_data_received(self, fd, data):
|
||||||
if fd in (1, 2):
|
from .console_script import console_script
|
||||||
|
debug = console_script.parser.options.get('debug', False)
|
||||||
|
|
||||||
|
if (debug is True or 'out' in str(debug)) and fd in (1, 2):
|
||||||
for line in data.split(b'\n'):
|
for line in data.split(b'\n'):
|
||||||
if not line:
|
if not line:
|
||||||
continue
|
continue
|
||||||
sys.stdout.buffer.write(
|
sys.stdout.buffer.write(
|
||||||
self.prefix.encode('utf8') + b' | ' + line + b'\n'
|
self.prefix.encode('utf8') + b' | ' + line + b'\n'
|
||||||
|
if self.prefix else line + b'\n'
|
||||||
)
|
)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
super().pipe_data_received(fd, data)
|
super().pipe_data_received(fd, data)
|
||||||
@ -38,26 +42,6 @@ def protocol_factory(prefix):
|
|||||||
loop=asyncio.events.get_event_loop()
|
loop=asyncio.events.get_event_loop()
|
||||||
)
|
)
|
||||||
return _p
|
return _p
|
||||||
'''
|
|
||||||
|
|
||||||
async def proc(args, prefix=None, wait=True, raises=True):
|
|
||||||
loop = asyncio.events.get_event_loop()
|
|
||||||
transport, protocol = await loop.subprocess_exec(
|
|
||||||
protocol_factory(prefix), *args)
|
|
||||||
proc = asyncio.subprocess.Process(transport, protocol, loop)
|
|
||||||
|
|
||||||
if wait:
|
|
||||||
stdout, stderr = await proc.communicate()
|
|
||||||
log['result'] = await proc.wait()
|
|
||||||
|
|
||||||
if raises and log['result']:
|
|
||||||
raise WrongResult()
|
|
||||||
|
|
||||||
if wait:
|
|
||||||
return log
|
|
||||||
|
|
||||||
return proc
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
class Proc:
|
class Proc:
|
||||||
@ -92,7 +76,13 @@ class Proc:
|
|||||||
if self.called:
|
if self.called:
|
||||||
raise Exception('Already called: ' + self.cmd)
|
raise Exception('Already called: ' + self.cmd)
|
||||||
|
|
||||||
|
from .console_script import console_script
|
||||||
|
debug = console_script.parser.options.get('debug', False)
|
||||||
|
if debug is True or 'proc' in str(debug):
|
||||||
|
if self.prefix:
|
||||||
print(f'{self.prefix} | + {self.cmd}')
|
print(f'{self.prefix} | + {self.cmd}')
|
||||||
|
else:
|
||||||
|
print(f'+ {self.cmd}')
|
||||||
|
|
||||||
loop = asyncio.events.get_event_loop()
|
loop = asyncio.events.get_event_loop()
|
||||||
transport, protocol = await loop.subprocess_exec(
|
transport, protocol = await loop.subprocess_exec(
|
||||||
@ -121,3 +111,8 @@ class Proc:
|
|||||||
if self.raises and self.proc.returncode:
|
if self.raises and self.proc.returncode:
|
||||||
raise WrongResult()
|
raise WrongResult()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@property
|
||||||
|
def json(self):
|
||||||
|
import json
|
||||||
|
return json.loads(self.out)
|
||||||
|
|||||||
@ -1,15 +1,30 @@
|
|||||||
|
import asyncio
|
||||||
|
import cli2
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
from .proc import Proc
|
from .proc import Proc
|
||||||
|
|
||||||
|
|
||||||
class Script:
|
class Script:
|
||||||
|
options = [
|
||||||
|
cli2.Option(
|
||||||
|
'debug',
|
||||||
|
alias='d',
|
||||||
|
color=cli2.GREEN,
|
||||||
|
help='''
|
||||||
|
Display debug output.
|
||||||
|
Supports values: proc,out,visit
|
||||||
|
'''
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
def __init__(self, name=None, doc=None):
|
def __init__(self, name=None, doc=None):
|
||||||
self.name = name or type(self).__name__.lower()
|
self.name = name or type(self).__name__.lower()
|
||||||
self.doc = doc or 'Custom script'
|
self.doc = doc or 'Custom script'
|
||||||
|
|
||||||
async def exec(self, *args, **kwargs):
|
async def exec(self, *args, **kwargs):
|
||||||
"""Execute a command on the host."""
|
"""Execute a command on the host."""
|
||||||
|
if getattr(self, 'container', None):
|
||||||
kwargs.setdefault('prefix', self.container.name)
|
kwargs.setdefault('prefix', self.container.name)
|
||||||
proc = await Proc(*args, **kwargs)()
|
proc = await Proc(*args, **kwargs)()
|
||||||
if kwargs.get('wait', True):
|
if kwargs.get('wait', True):
|
||||||
@ -17,6 +32,9 @@ class Script:
|
|||||||
return proc
|
return proc
|
||||||
|
|
||||||
async def __call__(self, visitable, *args, **kwargs):
|
async def __call__(self, visitable, *args, **kwargs):
|
||||||
|
from .console_script import console_script
|
||||||
|
debug = console_script.parser.options.get('debug', False)
|
||||||
|
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
@ -36,10 +54,10 @@ class Script:
|
|||||||
if not hasattr(visitor, method):
|
if not hasattr(visitor, method):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if debug is True or 'visit' in str(debug):
|
||||||
print(
|
print(
|
||||||
visitable.name + ' | ',
|
visitable.name + ' | ',
|
||||||
type(visitor).__name__,
|
'.'.join([type(visitor).__name__, method]),
|
||||||
method,
|
|
||||||
' '.join(f'{k}={v}' for k, v in visitor.__dict__.items())
|
' '.join(f'{k}={v}' for k, v in visitor.__dict__.items())
|
||||||
)
|
)
|
||||||
result = getattr(visitor, method)(self)
|
result = getattr(visitor, method)(self)
|
||||||
@ -49,3 +67,22 @@ class Script:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
await clean()
|
await clean()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
async def run(self, *args, **kwargs):
|
||||||
|
pod = kwargs.get('pod')
|
||||||
|
|
||||||
|
if args:
|
||||||
|
containers = [c for c in pod.containers if c.name in args]
|
||||||
|
else:
|
||||||
|
containers = pod.containers
|
||||||
|
|
||||||
|
procs = []
|
||||||
|
for container in containers:
|
||||||
|
procs.append(self(
|
||||||
|
container,
|
||||||
|
*args,
|
||||||
|
container=container,
|
||||||
|
**kwargs,
|
||||||
|
))
|
||||||
|
|
||||||
|
return await asyncio.gather(*procs)
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
from ..exceptions import WrongResult
|
||||||
|
|
||||||
CI_VARS = (
|
CI_VARS = (
|
||||||
# gitlab
|
# gitlab
|
||||||
'CI_COMMIT_SHORT_SHA',
|
'CI_COMMIT_SHORT_SHA',
|
||||||
@ -85,3 +87,13 @@ class Commit:
|
|||||||
'--name', script.container.name,
|
'--name', script.container.name,
|
||||||
':'.join((self.repo, self.tags[0])),
|
':'.join((self.repo, self.tags[0])),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def up(self, script):
|
||||||
|
name = '-'.join([script.pod.name, script.container.name])
|
||||||
|
try:
|
||||||
|
await script.exec('podman', 'inspect', name)
|
||||||
|
except WrongResult:
|
||||||
|
await script.exec(
|
||||||
|
'podman', 'run', '-d', '--name', name,
|
||||||
|
':'.join((self.repo, self.tags[0])),
|
||||||
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user