1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
|
import argparse
import collections
import os
import re
import ssg.build_yaml
import ssg.components
import ssg.environment
import ssg.rules
import ssg.yaml
def parse_args():
parser = argparse.ArgumentParser(
description="Test components data consistency")
parser.add_argument(
"--source-dir", help="Path to the root directory", required=True)
parser.add_argument(
"--build-dir", help="Path to the build directory", required=True)
parser.add_argument(
"--product", help="Product ID", required=True)
return parser.parse_args()
def test_template_name(
template, package_to_component, template_to_component):
template_name = template["name"]
if template_name in template_to_component:
component = template_to_component[template_name][0]
reason = (
"all rules using template '%s' must be assigned to component "
"'%s'" % (template_name, component))
return (component, reason)
return None
def test_template_package(
template, package_to_component, template_to_component):
template_name = template["name"]
template_vars = template["vars"]
if template_name in ["package_installed", "package_removed"]:
package = template_vars["pkgname"]
component = package_to_component.get(package, [package])[0]
reason = (
"rule uses template '%s' with 'pkgname' parameter set to '%s' "
"which is a package that already belongs to component '%s'" %
(template_name, package, component))
return (component, reason)
return None
def test_template_service(
template, package_to_component, template_to_component):
template_name = template["name"]
template_vars = template["vars"]
if template_name in ["service_enabled", "service_disabled"]:
if "packagename" in template_vars:
package = template_vars["packagename"]
else:
package = template_vars["servicename"]
component = package_to_component.get(package, [package])[0]
reason = (
"rule uses template '%s' checking service '%s' provided by "
"package '%s' which is a package that already belongs to "
"component '%s'" % (
template_name, template_vars["servicename"],
package, component))
return (component, reason)
return None
template_test_plugins = [
test_template_name,
test_template_package,
test_template_service,
]
def get_component_by_template(
rule, package_to_component, template_to_component):
template = rule.template
if not template:
return None
for plugin_function in template_test_plugins:
plugin_result = plugin_function(
template, package_to_component, template_to_component)
if plugin_result is not None:
return plugin_result
return None
def test_nonexistent_rules(rules_in_benchmark, rules_with_component):
nonexistent_rules = rules_with_component - rules_in_benchmark
if nonexistent_rules:
print("The following rules aren't part of the benchmark:")
for rule_id in nonexistent_rules:
print("- %s" % (rule_id))
return False
return True
def test_unmapped_rules(rules_in_benchmark, rules_with_component):
unmapped_rules = rules_in_benchmark - rules_with_component
if unmapped_rules:
print("The following rules aren't part of any component:")
for x in unmapped_rules:
print("- " + x)
return False
return True
def find_all_rules(base_dir):
for rule_dir in ssg.rules.find_rule_dirs(base_dir):
rule_id = ssg.rules.get_rule_dir_id(rule_dir)
yield rule_id
def iterate_over_resolved_rules(built_rules_dir):
for file_name in os.listdir(built_rules_dir):
file_path = os.path.join(built_rules_dir, file_name)
try:
rule = ssg.build_yaml.Rule.from_yaml(file_path)
except ssg.yaml.DocumentationNotComplete:
pass
yield rule
def test_templates(
rule, package_to_component, rule_components, template_to_component):
result = True
sub_outcome = get_component_by_template(
rule, package_to_component, template_to_component)
if sub_outcome is None:
return result
candidate, reason = sub_outcome
if candidate and candidate.lower() not in rule_components:
result = False
print(
"Rule '%s' must be assigned to component '%s', because %s." %
(rule.id_, candidate, reason))
return result
def test_package_platform(rule, package_to_component, rule_components):
match = re.match(r"package\[([\w\-_]+)\]", rule.platform)
if not match:
return True
result = True
for package in match.groups():
component = package_to_component.get(package, [package])[0]
if component not in rule_components:
print(
"Rule '%s' must be assigned to component '%s', "
"because it uses the package['%s'] platform." %
(rule.id_, component, package))
result = False
return result
def test_platform(rule, package_to_component, rule_components):
platform = rule.platform
if platform is None:
return True
result = True
if "package" in platform:
result = test_package_platform(
rule, package_to_component, rule_components)
component_exclusive_platforms = {
"grub2": "grub2",
"sssd-ldap": "sssd"
}
for e_platform, e_component in component_exclusive_platforms.items():
if platform == e_platform and e_component not in rule_components:
print(
"Rule '%s' must be assigned to component '%s', "
"because it uses the '%s' platform." %
(rule.id_, e_component, e_platform))
result = False
return result
def test_group(rule, rule_components, rule_groups, group_to_components):
result = True
for g in rule_groups:
components = group_to_components.get(g, [])
for c in components:
if c not in rule_components:
print(
"Rule '%s' must be in component '%s' because it's a "
"member of '%s' group." % (rule.id_, c, g))
result = False
return result
def get_rule_to_groups(groups_dir):
rule_to_groups = collections.defaultdict(list)
for file_name in os.listdir(groups_dir):
group_file_path = os.path.join(groups_dir, file_name)
group = ssg.build_yaml.Group.from_yaml(group_file_path)
for rule in group.rules:
rule_to_groups[rule].append(group.id_)
return rule_to_groups
def test_benchmark_rules(components, source_dir):
result = True
rule_to_components = ssg.components.rule_component_mapping(components)
rules_with_component = set(rule_to_components.keys())
linux_os_guide_dir = os.path.join(source_dir, "linux_os", "guide")
rules_in_benchmark = set(find_all_rules(linux_os_guide_dir))
if not test_nonexistent_rules(rules_in_benchmark, rules_with_component):
result = False
if not test_unmapped_rules(rules_in_benchmark, rules_with_component):
result = False
return result
def test_rule(rule, mappings):
(
rule_to_components, package_to_component, template_to_component,
rule_to_groups, group_to_components) = mappings
result = True
rule_components = rule_to_components[rule.id_]
rule_groups = rule_to_groups[rule.id_]
if not test_templates(
rule, package_to_component, rule_components,
template_to_component):
result = False
if not test_platform(rule, package_to_component, rule_components):
result = False
if not test_group(rule, rule_components, rule_groups, group_to_components):
result = False
return result
def test_resolved_rules(components, build_dir, product):
result = True
rule_to_components = ssg.components.rule_component_mapping(components)
package_to_component = ssg.components.package_component_mapping(
components)
template_to_component = ssg.components.template_component_mapping(
components)
group_to_components = ssg.components.group_component_mapping(components)
product_dir = os.path.join(build_dir, product)
groups_dir = os.path.join(product_dir, "groups")
rule_to_groups = get_rule_to_groups(groups_dir)
rules_dir = os.path.join(product_dir, "rules")
mappings = (
rule_to_components, package_to_component, template_to_component,
rule_to_groups, group_to_components)
for rule in iterate_over_resolved_rules(rules_dir):
if not test_rule(rule, mappings):
result = False
return result
def main():
args = parse_args()
components_dir = os.path.join(args.source_dir, "components")
components = ssg.components.load(components_dir)
result = 0
if not test_benchmark_rules(components, args.source_dir):
result = 1
if not test_resolved_rules(components, args.build_dir, args.product):
result = 1
exit(result)
if __name__ == "__main__":
main()
|