summaryrefslogtreecommitdiffstats
path: root/src/lib/Server/Lint
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/Server/Lint')
-rw-r--r--src/lib/Server/Lint/MergeFiles.py9
-rw-r--r--src/lib/Server/Lint/RequiredAttrs.py94
-rw-r--r--src/lib/Server/Lint/Validate.py18
-rw-r--r--src/lib/Server/Lint/__init__.py2
4 files changed, 75 insertions, 48 deletions
diff --git a/src/lib/Server/Lint/MergeFiles.py b/src/lib/Server/Lint/MergeFiles.py
index 27e7aa99a..52fea3d9b 100644
--- a/src/lib/Server/Lint/MergeFiles.py
+++ b/src/lib/Server/Lint/MergeFiles.py
@@ -1,7 +1,6 @@
import os
from copy import deepcopy
from difflib import SequenceMatcher
-import Bcfg2.Options
import Bcfg2.Server.Lint
class MergeFiles(Bcfg2.Server.Lint.ServerPlugin):
@@ -27,10 +26,10 @@ 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",
- "The following probes are similar: %s. "
- "Consider merging them into a single probe." %
- ", ".join([p for p in mset]))
+ self.LintError("merge-cfg",
+ "The following probes are similar: %s. "
+ "Consider merging them into a single probe." %
+ ", ".join([p for p in mset]))
def get_similar(self, entries):
if "threshold" in self.config:
diff --git a/src/lib/Server/Lint/RequiredAttrs.py b/src/lib/Server/Lint/RequiredAttrs.py
index a94bbb3ed..4d4e99f32 100644
--- a/src/lib/Server/Lint/RequiredAttrs.py
+++ b/src/lib/Server/Lint/RequiredAttrs.py
@@ -10,20 +10,33 @@ class RequiredAttrs(Bcfg2.Server.Lint.ServerPlugin):
def __init__(self, *args, **kwargs):
Bcfg2.Server.Lint.ServerPlugin.__init__(self, *args, **kwargs)
self.required_attrs = {
- 'device': ['name', 'owner', 'group', 'dev_type'],
- 'directory': ['name', 'owner', 'group', 'perms'],
- 'file': ['name', 'owner', 'group', 'perms'],
- 'hardlink': ['name', 'to'],
- 'symlink': ['name', 'to'],
- 'ignore': ['name'],
- 'nonexistent': ['name'],
- 'permissions': ['name', 'owner', 'group', 'perms'],
- 'vcs': ['vcstype', 'revision', 'sourceurl']}
+ 'Path': {
+ 'device': ['name', 'owner', 'group', 'dev_type'],
+ 'directory': ['name', 'owner', 'group', 'perms'],
+ 'file': ['name', 'owner', 'group', 'perms', '__text__'],
+ 'hardlink': ['name', 'to'],
+ 'symlink': ['name', 'to'],
+ 'ignore': ['name'],
+ 'nonexistent': ['name'],
+ 'permissions': ['name', 'owner', 'group', 'perms'],
+ 'vcs': ['vcstype', 'revision', 'sourceurl']},
+ 'Service': {
+ 'chkconfig': ['name'],
+ 'deb': ['name'],
+ 'rc-update': ['name'],
+ 'smf': ['name', 'FMRI'],
+ 'upstart': ['name']},
+ 'Action': ['name', 'timing', 'when', 'status', 'command'],
+ 'Package': ['name']}
def Run(self):
- self.check_rules()
- self.check_bundles()
self.check_packages()
+ if "Defaults" in self.core.plugins:
+ self.logger.info("Defaults plugin enabled; skipping required "
+ "attribute checks")
+ else:
+ self.check_rules()
+ self.check_bundles()
def check_packages(self):
""" check package sources for Source entries with missing attrs """
@@ -70,22 +83,34 @@ class RequiredAttrs(Bcfg2.Server.Lint.ServerPlugin):
except (lxml.etree.XMLSyntaxError, AttributeError):
xdata = lxml.etree.parse(bundle.template.filepath).getroot()
- for path in xdata.xpath("//BoundPath"):
+ for path in xdata.xpath("//*[substring(name(), 1, 5) = 'Bound']"):
self.check_entry(path, bundle.name)
def check_entry(self, entry, filename):
""" generic entry check """
if self.HandlesFile(filename):
- pathname = entry.get('name')
- pathtype = entry.get('type')
- pathset = set(entry.attrib.keys())
- try:
- required_attrs = set(self.required_attrs[pathtype] + ['type'])
- except KeyError:
- self.LintError("unknown-path-type",
- "Unknown path type %s: %s" %
- (pathtype, self.RenderXML(entry)))
- return
+ name = entry.get('name')
+ tag = entry.tag
+ if tag.startswith("Bound"):
+ tag = tag[5:]
+ if tag not in self.required_attrs:
+ self.LintError("unknown-entry-tag",
+ "Unknown entry tag '%s': %s" %
+ (entry.tag, self.RenderXML(entry)))
+
+ if isinstance(self.required_attrs[tag], dict):
+ etype = entry.get('type')
+ if etype in self.required_attrs[tag]:
+ required_attrs = set(self.required_attrs[tag][etype] +
+ ['type'])
+ else:
+ self.LintError("unknown-entry-type",
+ "Unknown %s type %s: %s" %
+ (tag, etype, self.RenderXML(entry)))
+ return
+ else:
+ required_attrs = set(self.required_attrs[tag])
+ attrs = set(entry.attrib.keys())
if 'dev_type' in required_attrs:
dev_type = entry.get('dev_type')
@@ -93,17 +118,20 @@ class RequiredAttrs(Bcfg2.Server.Lint.ServerPlugin):
# check if major/minor are specified
required_attrs |= set(['major', 'minor'])
- if pathtype == 'file' and not entry.text:
- self.LintError("required-attrs-missing",
- "Text missing for %s %s in %s: %s" %
- (entry.tag, pathname, filename,
- self.RenderXML(entry)))
+ if '__text__' in required_attrs:
+ required_attrs.pop('__text__')
+ if not entry.text:
+ self.LintError("required-attrs-missing",
+ "Text missing for %s %s in %s: %s" %
+ (entry.tag, name, filename,
+ self.RenderXML(entry)))
- if not pathset.issuperset(required_attrs):
+ if not attrs.issuperset(required_attrs):
self.LintError("required-attrs-missing",
- "The required attributes %s are missing for %s %sin %s:\n%s" %
- (",".join([attr
- for attr in
- required_attrs.difference(pathset)]),
- entry.tag, pathname, filename,
+ "The following required attribute(s) are "
+ "missing for %s %s in %s: %s\n%s" %
+ (entry.tag, name, filename,
+ ", ".join([attr
+ for attr in
+ required_attrs.difference(attrs)]),
self.RenderXML(entry)))
diff --git a/src/lib/Server/Lint/Validate.py b/src/lib/Server/Lint/Validate.py
index ebf621c22..19fd61d25 100644
--- a/src/lib/Server/Lint/Validate.py
+++ b/src/lib/Server/Lint/Validate.py
@@ -5,7 +5,6 @@ import os
from subprocess import Popen, PIPE, STDOUT
import sys
-import Bcfg2.Options
import Bcfg2.Server.Lint
class Validate(Bcfg2.Server.Lint.ServerlessPlugin):
@@ -21,6 +20,7 @@ class Validate(Bcfg2.Server.Lint.ServerlessPlugin):
"%s/Pkgmgr/*.xml":"%s/pkglist.xsd",
"%s/Base/*.xml":"%s/base.xsd",
"%s/Rules/*.xml":"%s/rules.xsd",
+ "%s/Defaults/*.xml":"%s/defaults.xsd",
"%s/etc/report-configuration.xml":"%s/report-configuration.xsd",
"%s/Svcmgr/*.xml":"%s/services.xsd",
"%s/Deps/*.xml":"%s/deps.xsd",
@@ -45,21 +45,21 @@ class Validate(Bcfg2.Server.Lint.ServerlessPlugin):
if filelist:
# avoid loading schemas for empty file lists
+ schemafile = schemaname % schemadir
try:
- schema = lxml.etree.XMLSchema(lxml.etree.parse(schemaname %
- schemadir))
+ schema = lxml.etree.XMLSchema(lxml.etree.parse(schemafile))
except IOError:
e = sys.exc_info()[1]
- self.LintError("input-output-error", e.message)
+ self.LintError("input-output-error", str(e))
continue
- except:
+ except lxml.etree.XMLSchemaParseError:
+ e = sys.exc_info()[1]
self.LintError("schema-failed-to-parse",
- "Failed to process schema %s" %
- (schemaname % schemadir))
+ "Failed to process schema %s: %s" %
+ (schemafile, e))
continue
for filename in filelist:
- self.validate(filename, schemaname % schemadir,
- schema=schema)
+ self.validate(filename, schemafile, schema=schema)
self.check_properties()
diff --git a/src/lib/Server/Lint/__init__.py b/src/lib/Server/Lint/__init__.py
index f15c90557..f47059ac4 100644
--- a/src/lib/Server/Lint/__init__.py
+++ b/src/lib/Server/Lint/__init__.py
@@ -107,7 +107,7 @@ class ErrorHandler (object):
"duplicate-package":"error",
"multiple-default-groups":"error",
"required-infoxml-attrs-missing":"error",
- "unknown-path-type":"error",
+ "unknown-entry-type":"error",
"required-attrs-missing":"error",
"extra-attrs":"warning",
"schema-failed-to-parse":"warning",