Passed
Push — master ( 13b0af...ea42c3 )
by Jan
13:56 queued 11:45
created

utils.render-policy.HtmlOutput.__init__()   A

Complexity

Conditions 1

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 8
nop 4
dl 0
loc 11
ccs 0
cts 8
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
#!/usr/bin/python3
2
3
from glob import glob
4
import collections
5
import os
6
import pathlib
7
8
import argparse
9
10
import ssg.build_yaml
11
import ssg.controls
12
import ssg.yaml
13
import ssg.jinja
14
15
16
class HtmlOutput(object):
17
    def __init__(self, product, build_dir, policy_file):
18
        self.project_directory = pathlib.Path(os.path.dirname(__file__)).parent.resolve()
19
20
        self.env_yaml = self.get_env_yaml(product, build_dir)
21
22
        policy = ssg.controls.Policy(policy_file, self.env_yaml)
23
        policy.load()
24
        self.policy = policy
25
26
        self.product = product
27
        self.rules_dict = self.get_rules_with_metadata(product, build_dir)
28
29
    def get_rules_with_metadata(self, product, build_dir):
30
        compiled_rules = "{build_dir}/{product}/rules".format(build_dir=build_dir, product=product)
31
        rule_files = glob("{compiled_rules}/*".format(compiled_rules=compiled_rules))
32
        if not rule_files:
33
            msg = (
34
                "No files found in '{compiled_rules}', please make sure that "
35
                "you select the build dir correctly and that the appropriate product is built."
36
                .format(compiled_rules=compiled_rules)
37
            )
38
            raise ValueError(msg)
39
        rules_dict = dict()
40
41
        for r_file in rule_files:
42
            rule = ssg.build_yaml.Rule.from_yaml(r_file, self.env_yaml)
43
            rule.relative_definition_location = (
44
                pathlib.PurePath(rule.definition_location)
45
                .relative_to(self.project_directory))
46
            rules_dict[rule.id_] = rule
47
        return rules_dict
48
49
    def get_env_yaml(self, product, build_dir):
50
        product_yaml = self.project_directory / product / "product.yml"
51
        build_config_yaml = pathlib.Path(build_dir) / "build_config.yml"
52
        if not (product_yaml.exists() and build_config_yaml.exists()):
53
            msg = (
54
                "No product yaml and/or build config found in "
55
                "'{product_yaml}' and/or '{build_config_yaml}', respectively, please make sure "
56
                "that you got the product right, and that it is built."
57
                .format(product_yaml=product_yaml, build_config_yaml=build_config_yaml)
58
            )
59
            raise ValueError(msg)
60
        env_yaml = ssg.yaml.open_environment(build_config_yaml, product_yaml)
61
        return env_yaml
62
63
    def get_result(self):
64
        subst_dict = dict(rules=self.rules_dict, product=self.product, policy=self.policy)
65
        subst_dict.update(self.env_yaml)
66
        html_jinja_template = os.path.join(os.path.dirname(__file__), "controls-template.html")
67
        return ssg.jinja.process_file(html_jinja_template, subst_dict)
68
69
70
def parse_args():
71
    parser = argparse.ArgumentParser(
72
        description="Render a policy file typically located in 'controls' directory "
73
        "of the project to HTML in a context of a product. "
74
        "The product must be built.")
75
    parser.add_argument(
76
        "policy", metavar="FILENAME", help="The policy YAML file")
77
    parser.add_argument(
78
        "product", metavar="PRODTYPE",
79
        help="Product that provides context to the policy. It must already be built")
80
    parser.add_argument("--build-dir", default="build", help="Path to the build directory")
81
    parser.add_argument("--output", help="The filename to generate")
82
    return parser.parse_args()
83
84
85
if __name__ == "__main__":
86
    args = parse_args()
87
    result = HtmlOutput(args.product, args.build_dir, args.policy).get_result()
88
    if not args.output:
89
        print(result)
90
    else:
91
        with open(args.output, "w") as outfile:
92
            outfile.write(result)
93