From 07096c454d3a75a868f86ba8ce2f3678af934808 Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Fri, 20 Apr 2012 11:59:53 -0400 Subject: changed the way bcfg2-lint errors are loaded to make it easier to write and use custom plugins --- src/lib/Bcfg2/Server/Lint/Bundles.py | 16 +++------ src/lib/Bcfg2/Server/Lint/Comments.py | 6 ++++ src/lib/Bcfg2/Server/Lint/Deltas.py | 5 ++- src/lib/Bcfg2/Server/Lint/Duplicates.py | 7 ++++ src/lib/Bcfg2/Server/Lint/Genshi.py | 4 ++- src/lib/Bcfg2/Server/Lint/GroupPatterns.py | 3 ++ src/lib/Bcfg2/Server/Lint/InfoXML.py | 7 +++- src/lib/Bcfg2/Server/Lint/MergeFiles.py | 8 +++-- src/lib/Bcfg2/Server/Lint/Pkgmgr.py | 4 ++- src/lib/Bcfg2/Server/Lint/RequiredAttrs.py | 8 ++++- src/lib/Bcfg2/Server/Lint/TemplateHelper.py | 8 +++++ src/lib/Bcfg2/Server/Lint/Validate.py | 9 +++++ src/lib/Bcfg2/Server/Lint/__init__.py | 51 +++++++---------------------- 13 files changed, 77 insertions(+), 59 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Bcfg2/Server/Lint/Bundles.py b/src/lib/Bcfg2/Server/Lint/Bundles.py index 0c95f7e72..44626b462 100644 --- a/src/lib/Bcfg2/Server/Lint/Bundles.py +++ b/src/lib/Bcfg2/Server/Lint/Bundles.py @@ -3,7 +3,6 @@ import Bcfg2.Server.Lint class Bundles(Bcfg2.Server.Lint.ServerPlugin): """ Perform various bundle checks """ - def Run(self): """ run plugin """ if 'Bundler' in self.core.plugins: @@ -15,6 +14,10 @@ class Bundles(Bcfg2.Server.Lint.ServerPlugin): Bcfg2.Server.Plugins.SGenshi.SGenshiTemplateFile): self.bundle_names(bundle) + def Errors(self): + return {"bundle-not-found":"error", + "inconsistent-bundle-name":"warning"} + def missing_bundles(self): """ find bundles listed in Metadata but not implemented in Bundler """ if self.files is None: @@ -48,14 +51,3 @@ class Bundles(Bcfg2.Server.Lint.ServerPlugin): self.LintError("inconsistent-bundle-name", "Inconsistent bundle name: filename is %s, bundle name is %s" % (fname, bname)) - - def sgenshi_groups(self, bundle): - """ ensure that Genshi Bundles do not include tags, - which are not supported """ - xdata = lxml.etree.parse(bundle.name) - groups = [self.RenderXML(g) - for g in xdata.getroottree().findall("//Group")] - if groups: - self.LintError("group-tag-not-allowed", - " tag is not allowed in SGenshi Bundle:\n%s" % - "\n".join(groups)) diff --git a/src/lib/Bcfg2/Server/Lint/Comments.py b/src/lib/Bcfg2/Server/Lint/Comments.py index 19e6c1167..e16469bb5 100644 --- a/src/lib/Bcfg2/Server/Lint/Comments.py +++ b/src/lib/Bcfg2/Server/Lint/Comments.py @@ -16,6 +16,12 @@ class Comments(Bcfg2.Server.Lint.ServerPlugin): self.check_infoxml() self.check_probes() + def Errors(self): + return {"unexpanded-keywords":"warning", + "keywords-not-found":"warning", + "comments-not-found":"warning", + "broken-xinclude-chain":"warning"} + def required_keywords(self, rtype): """ given a file type, fetch the list of required VCS keywords from the bcfg2-lint config """ diff --git a/src/lib/Bcfg2/Server/Lint/Deltas.py b/src/lib/Bcfg2/Server/Lint/Deltas.py index cf91d1d13..8d35d8e5a 100644 --- a/src/lib/Bcfg2/Server/Lint/Deltas.py +++ b/src/lib/Bcfg2/Server/Lint/Deltas.py @@ -2,7 +2,6 @@ import Bcfg2.Server.Lint class Deltas(Bcfg2.Server.Lint.ServerPlugin): """ Warn about usage of .cat and .diff files """ - def Run(self): """ run plugin """ if 'Cfg' in self.core.plugins: @@ -10,6 +9,10 @@ class Deltas(Bcfg2.Server.Lint.ServerPlugin): for basename, entry in list(cfg.entries.items()): self.check_entry(basename, entry) + def Errors(self): + return {"cat-file-used":"warning", + "diff-file-used":"warning"} + def check_entry(self, basename, entry): for fname in list(entry.entries.keys()): if self.HandlesFile(fname): diff --git a/src/lib/Bcfg2/Server/Lint/Duplicates.py b/src/lib/Bcfg2/Server/Lint/Duplicates.py index afddebb71..abc581c4f 100644 --- a/src/lib/Bcfg2/Server/Lint/Duplicates.py +++ b/src/lib/Bcfg2/Server/Lint/Duplicates.py @@ -22,6 +22,13 @@ class Duplicates(Bcfg2.Server.Lint.ServerPlugin): if self.clients_xdata is not None: self.duplicate_clients() + def Errors(self): + return {"broken-xinclude-chain":"warning", + "duplicate-client":"error", + "duplicate-group":"error", + "duplicate-package":"error", + "multiple-default-groups":"error"} + def load_xdata(self): """ attempt to load XML data for groups and clients. only actually load data if all documents reference in XIncludes can diff --git a/src/lib/Bcfg2/Server/Lint/Genshi.py b/src/lib/Bcfg2/Server/Lint/Genshi.py index c78366ae9..45ddf8f2f 100755 --- a/src/lib/Bcfg2/Server/Lint/Genshi.py +++ b/src/lib/Bcfg2/Server/Lint/Genshi.py @@ -3,7 +3,6 @@ import Bcfg2.Server.Lint class Genshi(Bcfg2.Server.Lint.ServerPlugin): """ Check Genshi templates for syntax errors """ - def Run(self): """ run plugin """ loader = genshi.template.TemplateLoader() @@ -12,6 +11,9 @@ class Genshi(Bcfg2.Server.Lint.ServerPlugin): self.check_files(self.core.plugins[plugin].entries, loader=loader) + def Errors(self): + return {"genshi-syntax-error":"error"} + def check_files(self, entries, loader=None): if loader is None: loader = genshi.template.TemplateLoader() diff --git a/src/lib/Bcfg2/Server/Lint/GroupPatterns.py b/src/lib/Bcfg2/Server/Lint/GroupPatterns.py index 2e0dffde7..f50118ce1 100644 --- a/src/lib/Bcfg2/Server/Lint/GroupPatterns.py +++ b/src/lib/Bcfg2/Server/Lint/GroupPatterns.py @@ -14,6 +14,9 @@ class GroupPatterns(Bcfg2.Server.Lint.ServerPlugin): self.check(entry, groups, ptype='NamePattern') self.check(entry, groups, ptype='NameRange') + def Errors(self): + return {"pattern-fails-to-initialize":"error"} + def check(self, entry, groups, ptype="NamePattern"): if ptype == "NamePattern": pmap = lambda p: PatternMap(p, None, groups) diff --git a/src/lib/Bcfg2/Server/Lint/InfoXML.py b/src/lib/Bcfg2/Server/Lint/InfoXML.py index 2054e23bf..20c218e6f 100644 --- a/src/lib/Bcfg2/Server/Lint/InfoXML.py +++ b/src/lib/Bcfg2/Server/Lint/InfoXML.py @@ -4,7 +4,6 @@ import Bcfg2.Server.Lint class InfoXML(Bcfg2.Server.Lint.ServerPlugin): """ ensure that all config files have an info.xml file""" - def Run(self): if 'Cfg' in self.core.plugins: for filename, entryset in self.core.plugins['Cfg'].entries.items(): @@ -18,6 +17,12 @@ class InfoXML(Bcfg2.Server.Lint.ServerPlugin): self.LintError("no-infoxml", "No info.xml found for %s" % filename) + def Errors(self): + return {"no-infoxml":"warning", + "paranoid-false":"warning", + "broken-xinclude-chain":"warning", + "required-infoxml-attrs-missing":"error"} + def check_infoxml(self, fname, xdata): for info in xdata.getroottree().findall("//Info"): required = [] diff --git a/src/lib/Bcfg2/Server/Lint/MergeFiles.py b/src/lib/Bcfg2/Server/Lint/MergeFiles.py index 56bca7931..3259aca44 100644 --- a/src/lib/Bcfg2/Server/Lint/MergeFiles.py +++ b/src/lib/Bcfg2/Server/Lint/MergeFiles.py @@ -6,13 +6,17 @@ import Bcfg2.Server.Lint class MergeFiles(Bcfg2.Server.Lint.ServerPlugin): """ find Probes or Cfg files with multiple similar files that might be merged into one """ - def Run(self): if 'Cfg' in self.core.plugins: self.check_cfg() if 'Probes' in self.core.plugins: self.check_probes() + def Errors(self): + return {"merge-cfg":"warning", + "merge-probes":"warning"} + + def check_cfg(self): for filename, entryset in self.core.plugins['Cfg'].entries.items(): for mset in self.get_similar(entryset.entries): @@ -26,7 +30,7 @@ class MergeFiles(Bcfg2.Server.Lint.ServerPlugin): def check_probes(self): probes = self.core.plugins['Probes'].probes.entries for mset in self.get_similar(probes): - self.LintError("merge-cfg", + self.LintError("merge-probes", "The following probes are similar: %s. " "Consider merging them into a single probe." % ", ".join([p for p in mset])) diff --git a/src/lib/Bcfg2/Server/Lint/Pkgmgr.py b/src/lib/Bcfg2/Server/Lint/Pkgmgr.py index 8f099163a..7c17d555a 100644 --- a/src/lib/Bcfg2/Server/Lint/Pkgmgr.py +++ b/src/lib/Bcfg2/Server/Lint/Pkgmgr.py @@ -4,7 +4,6 @@ import Bcfg2.Server.Lint class Pkgmgr(Bcfg2.Server.Lint.ServerlessPlugin): """ find duplicate Pkgmgr entries with the same priority """ - def Run(self): pset = set() for pfile in glob.glob("%s/Pkgmgr/*.xml" % self.config['repo']): @@ -33,3 +32,6 @@ class Pkgmgr(Bcfg2.Server.Lint.ServerlessPlugin): (pkg.get('name'), priority, ptype)) else: pset.add(ptuple) + + def Errors(self): + return {"duplicate-packages":"error"} diff --git a/src/lib/Bcfg2/Server/Lint/RequiredAttrs.py b/src/lib/Bcfg2/Server/Lint/RequiredAttrs.py index 55206d2ba..20947d50f 100644 --- a/src/lib/Bcfg2/Server/Lint/RequiredAttrs.py +++ b/src/lib/Bcfg2/Server/Lint/RequiredAttrs.py @@ -6,7 +6,6 @@ from Bcfg2.Server.Plugins.Packages import Apt, Yum class RequiredAttrs(Bcfg2.Server.Lint.ServerPlugin): """ verify attributes for configuration entries (as defined in doc/server/configurationentries) """ - def __init__(self, *args, **kwargs): Bcfg2.Server.Lint.ServerPlugin.__init__(self, *args, **kwargs) self.required_attrs = { @@ -38,6 +37,13 @@ class RequiredAttrs(Bcfg2.Server.Lint.ServerPlugin): self.check_rules() self.check_bundles() + def Errors(self): + return {"unknown-entry-type":"error", + "unknown-entry-tag":"error", + "required-attrs-missing":"error", + "extra-attrs":"warning"} + + def check_packages(self): """ check package sources for Source entries with missing attrs """ if 'Packages' in self.core.plugins: diff --git a/src/lib/Bcfg2/Server/Lint/TemplateHelper.py b/src/lib/Bcfg2/Server/Lint/TemplateHelper.py index b8adcd8ec..f5f916e88 100644 --- a/src/lib/Bcfg2/Server/Lint/TemplateHelper.py +++ b/src/lib/Bcfg2/Server/Lint/TemplateHelper.py @@ -53,3 +53,11 @@ class TemplateHelper(Bcfg2.Server.Lint.ServerlessPlugin): self.LintError("templatehelper-underscore-export", "%s: exported symbol %s starts with underscore" % (helper, sym)) + + def Errors(self): + return {"templatehelper-import-error":"error", + "templatehelper-no-export":"error", + "templatehelper-nonlist-export":"error", + "templatehelper-nonexistent-export":"error", + "templatehelper-reserved-export":"error", + "templatehelper-underscore-export":"warning"} diff --git a/src/lib/Bcfg2/Server/Lint/Validate.py b/src/lib/Bcfg2/Server/Lint/Validate.py index 012d65894..812ab3d00 100644 --- a/src/lib/Bcfg2/Server/Lint/Validate.py +++ b/src/lib/Bcfg2/Server/Lint/Validate.py @@ -63,6 +63,15 @@ class Validate(Bcfg2.Server.Lint.ServerlessPlugin): self.check_properties() + def Errors(self): + return {"broken-xinclude-chain":"warning", + "schema-failed-to-parse":"warning", + "properties-schema-not-found":"warning", + "xml-failed-to-parse":"error", + "xml-failed-to-read":"error", + "xml-failed-to-verify":"error", + "input-output-error":"error"} + def check_properties(self): """ check Properties files against their schemas """ for filename in self.filelists['props']: diff --git a/src/lib/Bcfg2/Server/Lint/__init__.py b/src/lib/Bcfg2/Server/Lint/__init__.py index 581fa3566..3a86709c0 100644 --- a/src/lib/Bcfg2/Server/Lint/__init__.py +++ b/src/lib/Bcfg2/Server/Lint/__init__.py @@ -54,14 +54,19 @@ class Plugin (object): self.config = config self.logger = logging.getLogger('bcfg2-lint') if errorhandler is None: - self.errorHandler = ErrorHandler() + self.errorhandler = ErrorHandler() else: - self.errorHandler = errorhandler + self.errorhandler = errorhandler + self.errorhandler.RegisterErrors(self.Errors()) def Run(self): """ run the plugin. must be overloaded by child classes """ pass + def Errors(self): + """ returns a dict of errors the plugin supplies. must be + overloaded by child classes """ + def HandlesFile(self, fname): """ returns true if the given file should be handled by the plugin according to the files list, false otherwise """ @@ -73,7 +78,7 @@ class Plugin (object): fname)) in self.files) def LintError(self, err, msg): - self.errorHandler.dispatch(err, msg) + self.errorhandler.dispatch(err, msg) def RenderXML(self, element): """render an XML element for error output -- line number @@ -92,42 +97,6 @@ class Plugin (object): class ErrorHandler (object): # how to handle different errors by default - _errors = {"no-infoxml":"warning", - "paranoid-false":"warning", - "bundle-not-found":"error", - "inconsistent-bundle-name":"warning", - "group-tag-not-allowed":"error", - "unexpanded-keywords":"warning", - "keywords-not-found":"warning", - "comments-not-found":"warning", - "broken-xinclude-chain":"warning", - "duplicate-client":"error", - "duplicate-group":"error", - "duplicate-package":"error", - "multiple-default-groups":"error", - "required-infoxml-attrs-missing":"error", - "unknown-entry-type":"error", - "required-attrs-missing":"error", - "extra-attrs":"warning", - "schema-failed-to-parse":"warning", - "properties-schema-not-found":"warning", - "xml-failed-to-parse":"error", - "xml-failed-to-read":"error", - "xml-failed-to-verify":"error", - "merge-cfg":"warning", - "merge-probes":"warning", - "input-output-error":"error", - "genshi-syntax-error":"error", - "pattern-fails-to-initialize":"error", - "cat-file-used":"warning", - "diff-file-used":"warning", - "templatehelper-import-error":"error", - "templatehelper-no-export":"error", - "templatehelper-nonlist-export":"error", - "templatehelper-nonexistent-export":"error", - "templatehelper-reserved-export":"error", - "templatehelper-underscore-export":"warning"} - def __init__(self, config=None): self.errors = 0 self.warnings = 0 @@ -152,7 +121,8 @@ class ErrorHandler (object): else: self._handlers[err] = self.debug - for err, action in self._errors.items(): + def RegisterErrors(self, errors): + for err, action in errors.items(): if err not in self._handlers: if "warn" in action: self._handlers[err] = self.warn @@ -160,6 +130,7 @@ class ErrorHandler (object): self._handlers[err] = self.error else: self._handlers[err] = self.debug + def dispatch(self, err, msg): if err in self._handlers: -- cgit v1.2.3-1-g7c22