Move the run part of LoraxTemplateRunner into new TemplateRunner class
This will make it easier to add a new subclass that only handles installpkg for use with livemedia-creator and lorax-composer iso creation.
This commit is contained in:
parent
a0ff34dcb1
commit
8eaad3bc5e
@ -103,19 +103,13 @@ def rexists(pathname, root=""):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# TODO: operate inside an actual chroot for safety? Not that RPM bothers..
|
class TemplateRunner(object):
|
||||||
class LoraxTemplateRunner(object):
|
|
||||||
'''
|
'''
|
||||||
This class parses and executes Lorax templates. Sample usage:
|
This class parses and executes Lorax templates. Sample usage:
|
||||||
|
|
||||||
# install a bunch of packages
|
# install a bunch of packages
|
||||||
runner = LoraxTemplateRunner(inroot=rundir, outroot=rundir, dbo=dnf_obj)
|
runner = LoraxTemplateRunner(inroot=rundir, outroot=rundir, dbo=dnf_obj)
|
||||||
runner.run("install-packages.ltmpl")
|
runner.run("install-packages.ltmpl")
|
||||||
|
|
||||||
# modify a runtime dir
|
|
||||||
runner = LoraxTemplateRunner(inroot=rundir, outroot=newrun)
|
|
||||||
runner.run("runtime-transmogrify.ltmpl")
|
|
||||||
|
|
||||||
NOTES:
|
NOTES:
|
||||||
|
|
||||||
* Parsing procedure is roughly:
|
* Parsing procedure is roughly:
|
||||||
@ -129,6 +123,75 @@ class LoraxTemplateRunner(object):
|
|||||||
|
|
||||||
* Parsing and execution are *separate* passes - so you can't use the result
|
* Parsing and execution are *separate* passes - so you can't use the result
|
||||||
of a command in an %if statement (or any other control statements)!
|
of a command in an %if statement (or any other control statements)!
|
||||||
|
'''
|
||||||
|
def __init__(self, fatalerrors=True, templatedir=None, defaults=None, builtins=None):
|
||||||
|
self.fatalerrors = fatalerrors
|
||||||
|
self.templatedir = templatedir or "/usr/share/lorax"
|
||||||
|
self.templatefile = None
|
||||||
|
self.builtins = builtins or {}
|
||||||
|
self.defaults = defaults or {}
|
||||||
|
|
||||||
|
|
||||||
|
def run(self, templatefile, **variables):
|
||||||
|
for k,v in list(self.defaults.items()) + list(self.builtins.items()):
|
||||||
|
variables.setdefault(k,v)
|
||||||
|
logger.debug("executing %s with variables=%s", templatefile, variables)
|
||||||
|
self.templatefile = templatefile
|
||||||
|
t = LoraxTemplate(directories=[self.templatedir])
|
||||||
|
commands = t.parse(templatefile, variables)
|
||||||
|
self._run(commands)
|
||||||
|
|
||||||
|
|
||||||
|
def _run(self, parsed_template):
|
||||||
|
logger.info("running %s", self.templatefile)
|
||||||
|
for (num, line) in enumerate(parsed_template,1):
|
||||||
|
logger.debug("template line %i: %s", num, " ".join(line))
|
||||||
|
skiperror = False
|
||||||
|
(cmd, args) = (line[0], line[1:])
|
||||||
|
# Following Makefile convention, if the command is prefixed with
|
||||||
|
# a dash ('-'), we'll ignore any errors on that line.
|
||||||
|
if cmd.startswith('-'):
|
||||||
|
cmd = cmd[1:]
|
||||||
|
skiperror = True
|
||||||
|
try:
|
||||||
|
# grab the method named in cmd and pass it the given arguments
|
||||||
|
f = getattr(self, cmd, None)
|
||||||
|
if cmd[0] == '_' or cmd == 'run' or not isinstance(f, collections.Callable):
|
||||||
|
raise ValueError("unknown command %s" % cmd)
|
||||||
|
f(*args)
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
if skiperror:
|
||||||
|
logger.debug("ignoring error")
|
||||||
|
continue
|
||||||
|
logger.error("template command error in %s:", self.templatefile)
|
||||||
|
logger.error(" %s", " ".join(line))
|
||||||
|
# format the exception traceback
|
||||||
|
exclines = traceback.format_exception(*sys.exc_info())
|
||||||
|
# skip the bit about "ltmpl.py, in _run()" - we know that
|
||||||
|
exclines.pop(1)
|
||||||
|
# log the "ErrorType: this is what happened" line
|
||||||
|
logger.error(" %s", exclines[-1].strip())
|
||||||
|
# and log the entire traceback to the debug log
|
||||||
|
for _line in ''.join(exclines).splitlines():
|
||||||
|
logger.debug(" %s", _line)
|
||||||
|
if self.fatalerrors:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
# TODO: operate inside an actual chroot for safety? Not that RPM bothers..
|
||||||
|
class LoraxTemplateRunner(TemplateRunner):
|
||||||
|
'''
|
||||||
|
This class parses and executes Lorax templates. Sample usage:
|
||||||
|
|
||||||
|
# install a bunch of packages
|
||||||
|
runner = LoraxTemplateRunner(inroot=rundir, outroot=rundir, dbo=dnf_obj)
|
||||||
|
runner.run("install-packages.ltmpl")
|
||||||
|
|
||||||
|
# modify a runtime dir
|
||||||
|
runner = LoraxTemplateRunner(inroot=rundir, outroot=newrun)
|
||||||
|
runner.run("runtime-transmogrify.ltmpl")
|
||||||
|
|
||||||
|
NOTES:
|
||||||
|
|
||||||
* Commands that run external programs (e.g. systemctl) currently use
|
* Commands that run external programs (e.g. systemctl) currently use
|
||||||
the *host*'s copy of that program, which may cause problems if there's a
|
the *host*'s copy of that program, which may cause problems if there's a
|
||||||
@ -152,14 +215,11 @@ class LoraxTemplateRunner(object):
|
|||||||
self.inroot = inroot
|
self.inroot = inroot
|
||||||
self.outroot = outroot
|
self.outroot = outroot
|
||||||
self.dbo = dbo
|
self.dbo = dbo
|
||||||
self.fatalerrors = fatalerrors
|
builtins = DataHolder(exists=lambda p: rexists(p, root=inroot),
|
||||||
self.templatedir = templatedir or "/usr/share/lorax"
|
|
||||||
self.templatefile = None
|
|
||||||
# some builtin methods
|
|
||||||
self.builtins = DataHolder(exists=lambda p: rexists(p, root=inroot),
|
|
||||||
glob=lambda g: list(rglob(g, root=inroot)))
|
glob=lambda g: list(rglob(g, root=inroot)))
|
||||||
self.defaults = defaults or {}
|
|
||||||
self.results = DataHolder(treeinfo=dict()) # just treeinfo for now
|
self.results = DataHolder(treeinfo=dict()) # just treeinfo for now
|
||||||
|
|
||||||
|
super(LoraxTemplateRunner, self).__init__(fatalerrors, templatedir, defaults, builtins)
|
||||||
# TODO: set up custom logger with a filter to add line info
|
# TODO: set up custom logger with a filter to add line info
|
||||||
|
|
||||||
def _out(self, path):
|
def _out(self, path):
|
||||||
@ -210,51 +270,6 @@ class LoraxTemplateRunner(object):
|
|||||||
for pkg in debug_pkgs:
|
for pkg in debug_pkgs:
|
||||||
f.write("%s\n" % pkg)
|
f.write("%s\n" % pkg)
|
||||||
|
|
||||||
def run(self, templatefile, **variables):
|
|
||||||
for k,v in list(self.defaults.items()) + list(self.builtins.items()):
|
|
||||||
variables.setdefault(k,v)
|
|
||||||
logger.debug("executing %s with variables=%s", templatefile, variables)
|
|
||||||
self.templatefile = templatefile
|
|
||||||
t = LoraxTemplate(directories=[self.templatedir])
|
|
||||||
commands = t.parse(templatefile, variables)
|
|
||||||
self._run(commands)
|
|
||||||
|
|
||||||
|
|
||||||
def _run(self, parsed_template):
|
|
||||||
logger.info("running %s", self.templatefile)
|
|
||||||
for (num, line) in enumerate(parsed_template,1):
|
|
||||||
logger.debug("template line %i: %s", num, " ".join(line))
|
|
||||||
skiperror = False
|
|
||||||
(cmd, args) = (line[0], line[1:])
|
|
||||||
# Following Makefile convention, if the command is prefixed with
|
|
||||||
# a dash ('-'), we'll ignore any errors on that line.
|
|
||||||
if cmd.startswith('-'):
|
|
||||||
cmd = cmd[1:]
|
|
||||||
skiperror = True
|
|
||||||
try:
|
|
||||||
# grab the method named in cmd and pass it the given arguments
|
|
||||||
f = getattr(self, cmd, None)
|
|
||||||
if cmd[0] == '_' or cmd == 'run' or not isinstance(f, collections.Callable):
|
|
||||||
raise ValueError("unknown command %s" % cmd)
|
|
||||||
f(*args)
|
|
||||||
except Exception: # pylint: disable=broad-except
|
|
||||||
if skiperror:
|
|
||||||
logger.debug("ignoring error")
|
|
||||||
continue
|
|
||||||
logger.error("template command error in %s:", self.templatefile)
|
|
||||||
logger.error(" %s", " ".join(line))
|
|
||||||
# format the exception traceback
|
|
||||||
exclines = traceback.format_exception(*sys.exc_info())
|
|
||||||
# skip the bit about "ltmpl.py, in _run()" - we know that
|
|
||||||
exclines.pop(1)
|
|
||||||
# log the "ErrorType: this is what happened" line
|
|
||||||
logger.error(" %s", exclines[-1].strip())
|
|
||||||
# and log the entire traceback to the debug log
|
|
||||||
for _line in ''.join(exclines).splitlines():
|
|
||||||
logger.debug(" %s", _line)
|
|
||||||
if self.fatalerrors:
|
|
||||||
raise
|
|
||||||
|
|
||||||
def install(self, srcglob, dest):
|
def install(self, srcglob, dest):
|
||||||
'''
|
'''
|
||||||
install SRC DEST
|
install SRC DEST
|
||||||
|
Loading…
Reference in New Issue
Block a user