shlax/podctl/container.py
2020-01-24 19:26:43 +01:00

110 lines
3.1 KiB
Python

import collections
import copy
from glob import glob
import subprocess
from .build import BuildScript
PACKAGE_MANAGERS = dict(
apk=dict(
update='apk update',
upgrade='apk upgrade',
install='apk add',
),
)
class Container(collections.UserDict):
cfg = dict()
def __init__(self, profile=None, **cfg):
newcfg = copy.deepcopy(self.cfg)
newcfg.update(cfg)
super().__init__(**newcfg)
self.profile = profile or 'default'
def __getitem__(self, name, type=None):
try:
result = super().__getitem__(name)
except KeyError:
if hasattr(self, name + '_get'):
result = self[name] = getattr(self, name + '_get')()
else:
raise
else:
if isinstance(result, (dict, list, tuple, switch)):
return self.switch_value(result)
return result
def switch_value(self, value):
_switch = lambda v: v.value(self) if isinstance(v, switch) else v
if isinstance(value, dict):
return {
k: self.switch_value(v)
for k, v in value.items()
if self.switch_value(v) is not None
}
elif isinstance(value, (list, tuple)):
return [
self.switch_value(i)
for i in value
if self.switch_value(i) is not None
]
else:
return _switch(value)
def script_build(self):
return BuildScript(self)
def package_manager_get(self):
for mgr in PACKAGE_MANAGERS.keys():
cmd = ['podman', 'run', self['base'], 'which', mgr]
try:
subprocess.check_call(cmd)
return mgr
break
except subprocess.CalledProcessError:
continue
raise Exception('Package manager not supported yet')
def package_manager_cmd(self, cmd):
return PACKAGE_MANAGERS[self['package_manager']][cmd]
def packages_install(self, script):
cache = f'.cache/{self["package_manager"]}'
script.mount(
'$(pwd)/' + cache,
f'/var/cache/{self["package_manager"]}'
)
cached = False
if self['package_manager'] == 'apk':
# special step to enable apk cache
script.run('ln -s /var/cache/apk /etc/apk/cache')
script.append(f'''
if [ -n "$(find .cache/apk/ -name APKINDEX.* -mtime +3)" ]; then
buildah run $ctr -- {self.package_manager_cmd("update")}
fi
''')
script.run(self.package_manager_cmd('upgrade'))
script.run(' '.join([
self.package_manager_cmd('install'),
' '.join(self.get('packages', []))
]))
class switch:
def __init__(self, **values):
"""Instanciate a switch to vary values based on container profile."""
self.values = values
def value(self, container):
"""Return value from container profile or default."""
return self.values.get(
container.profile,
self.values.get('default', None)
)