Commit 2c44b83a authored by Ad Schellevis's avatar Ad Schellevis

(configd/templates) add "template cleanup" command, closes...

(configd/templates) add "template cleanup" command, closes https://github.com/opnsense/core/issues/1238
parent 3df93860
...@@ -6,6 +6,13 @@ message:generate template %s ...@@ -6,6 +6,13 @@ message:generate template %s
config:/conf/config.xml config:/conf/config.xml
root_dir:/ root_dir:/
[cleanup]
command:template.cleanup
parameters:%s
type:inline
message:cleanup template %s
root_dir:/
[list] [list]
command:template.list command:template.list
type:inline type:inline
......
...@@ -65,15 +65,26 @@ def execute(action, parameters): ...@@ -65,15 +65,26 @@ def execute(action, parameters):
# traverse all installed templates and return list # traverse all installed templates and return list
# the number of registered targets is returned between [] # the number of registered targets is returned between []
tmpl = template.Template(action.root_dir) tmpl = template.Template(action.root_dir)
all_templates = tmpl.list_modules()
retval = [] retval = []
for tag in sorted(all_templates.keys()): for module_name in sorted(tmpl.list_modules()):
template_name = '%s [%d]' % (tag, len(all_templates[tag]['+TARGETS'])) template_count = len(tmpl.list_module(module_name)['+TARGETS'])
template_name = '%s [%d]' % (module_name, template_count)
retval.append(template_name) retval.append(template_name)
del tmpl del tmpl
return '\n'.join(retval) return '\n'.join(retval)
elif action.command == 'template.cleanup':
tmpl = template.Template(action.root_dir)
filenames = tmpl.cleanup(parameters)
del tmpl
# send generated filenames to syslog
if filenames is not None:
for filename in filenames:
syslog.syslog(syslog.LOG_DEBUG, ' %s removed %s' % (parameters, filename))
return 'OK'
else:
return 'ERR'
elif action.command == 'configd.actions': elif action.command == 'configd.actions':
# list all available configd actions # list all available configd actions
from processhandler import ActionHandler from processhandler import ActionHandler
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
import os import os
import os.path import os.path
import glob
import stat import stat
import syslog import syslog
import collections import collections
...@@ -58,33 +59,22 @@ class Template(object): ...@@ -58,33 +59,22 @@ class Template(object):
self._j2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(self._template_dir), trim_blocks=True, self._j2_env = jinja2.Environment(loader=jinja2.FileSystemLoader(self._template_dir), trim_blocks=True,
extensions=["jinja2.ext.do", "jinja2.ext.loopcontrols"]) extensions=["jinja2.ext.do", "jinja2.ext.loopcontrols"])
@staticmethod
def _read_targets(filename):
""" read raw target filename masks
:param filename: targets filename (path/+TARGETS)
:return: dictionary containing +TARGETS filename sets
"""
result = {}
for line in open(filename, 'r').read().split('\n'):
parts = line.split(':')
if len(parts) > 1 and parts[0].strip()[0] != '#':
result[parts[0]] = ':'.join(parts[1:]).strip()
return result
def list_module(self, module_name): def list_module(self, module_name):
""" list single module content """ list single module content
:param module_name: module name in dot notation ( company.module ) :param module_name: module name in dot notation ( company.module )
:return: dictionary with module data :return: dictionary with module data
""" """
result = {} result = {'+TARGETS': dict(), '+CLEANUP_TARGETS': dict()}
file_path = '%s/%s' % (self._template_dir, module_name.replace('.', '/')) file_path = '%s/%s' % (self._template_dir, module_name.replace('.', '/'))
if os.path.exists('%s/+TARGETS' % file_path): if os.path.exists('%s/+TARGETS' % file_path):
result['+TARGETS'] = self._read_targets('%s/+TARGETS' % file_path) for line in open('%s/+TARGETS' % file_path, 'r').read().split('\n'):
else: parts = line.split(':')
result['+TARGETS'] = {} if len(parts) > 1 and parts[0].strip()[0] != '#':
result['+TARGETS'][parts[0]] = parts[1].strip()
if len(parts) == 2:
result['+CLEANUP_TARGETS'][parts[0]] = parts[1].strip()
elif parts[2].strip() != "":
result['+CLEANUP_TARGETS'][parts[0]] = parts[2].strip()
return result return result
def list_modules(self): def list_modules(self):
...@@ -93,12 +83,11 @@ class Template(object): ...@@ -93,12 +83,11 @@ class Template(object):
:return: list (dict) of registered modules :return: list (dict) of registered modules
""" """
result = {} result =list()
for root, dirs, files in os.walk(self._template_dir): for root, dirs, files in os.walk(self._template_dir):
if root.count('/') > self._template_dir.count('/'): if root.count('/') > self._template_dir.count('/'):
module_name = root.replace(self._template_dir, '') module_name = root.replace(self._template_dir, '')
if module_name not in result: result.append(module_name)
result[module_name] = self.list_module(module_name)
return result return result
...@@ -274,14 +263,12 @@ class Template(object): ...@@ -274,14 +263,12 @@ class Template(object):
return result return result
def generate(self, module_name, create_directory=True): def iter_modules(self, module_name):
""" """
:param module_name: module name in dot notation ( company.module ), may use wildcards :param module_name: module name in dot notation ( company.module ), may use wildcards
:param create_directory: automatically create directories to place template output in ( if not existing ) :return: templates matching paterns
:return: list of generated output files or None if template not found
""" """
result = None for template_name in sorted(self.list_modules()):
for template_name in sorted(self.list_modules().keys()):
wildcard_pos = module_name.find('*') wildcard_pos = module_name.find('*')
do_generate = False do_generate = False
if wildcard_pos > -1 and module_name[:wildcard_pos] == template_name[:wildcard_pos]: if wildcard_pos > -1 and module_name[:wildcard_pos] == template_name[:wildcard_pos]:
...@@ -296,19 +283,45 @@ class Template(object): ...@@ -296,19 +283,45 @@ class Template(object):
do_generate = True do_generate = True
if do_generate: if do_generate:
if result is None: yield template_name
result = list()
syslog.syslog(syslog.LOG_NOTICE, "generate template container %s" % template_name) def generate(self, module_name, create_directory=True):
try: """
for filename in self._generate(template_name, create_directory): :param module_name: module name in dot notation ( company.module ), may use wildcards
result.append(filename) :param create_directory: automatically create directories to place template output in ( if not existing )
except Exception as render_exception: :return: list of generated output files or None if template not found
if wildcard_pos > -1: """
# log failure, but proceed processing when doing a wildcard search result = None
syslog.syslog(syslog.LOG_ERR, 'error generating template %s : %s' % (template_name, for template_name in self.iter_modules(module_name):
traceback.format_exc())) if result is None:
else: result = list()
raise render_exception syslog.syslog(syslog.LOG_NOTICE, "generate template container %s" % template_name)
try:
for filename in self._generate(template_name, create_directory):
result.append(filename)
except Exception as render_exception:
if wildcard_pos > -1:
# log failure, but proceed processing when doing a wildcard search
syslog.syslog(syslog.LOG_ERR, 'error generating template %s : %s' % (template_name,
traceback.format_exc()))
else:
raise render_exception
return result
def cleanup(self, module_name):
"""
:param module_name: module name in dot notation ( company.module ), may use wildcards
:return: list of removed files or None if template not found
"""
result = list()
for template_name in self.iter_modules(module_name):
syslog.syslog(syslog.LOG_NOTICE, "cleanup template container %s" % template_name)
module_data = self.list_module(module_name)
for src_template in module_data['+CLEANUP_TARGETS'].keys():
target = module_data['+CLEANUP_TARGETS'][src_template]
for filename in glob.glob(target):
os.remove(filename)
result.append(filename)
return result return result
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment