File: template_renderer.py

package info (click to toggle)
scap-security-guide 0.1.76-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 110,644 kB
  • sloc: xml: 241,883; sh: 73,777; python: 32,527; makefile: 27
file content (127 lines) | stat: -rw-r--r-- 4,892 bytes parent folder | download
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
#!/usr/bin/python3

import os

import argparse

import ssg.build_yaml
import ssg.controls
import ssg.environment
import ssg.jinja


def render_template(data, template_path, output_filename):
    loader = FlexibleLoader(os.path.dirname(template_path))
    return ssg.jinja.render_template(
        data, template_path, output_filename, loader)


"""
Loader that extends the AbsolutePathFileSystemLoader so it accepts
relative paths of templates if those are located in selected directories.

This is intended to be used when templates reference other templates.
"""
class FlexibleLoader(ssg.jinja.AbsolutePathFileSystemLoader):
    def __init__(self, lookup_dirs=None, ** kwargs):
        super(FlexibleLoader, self).__init__(** kwargs)
        self.lookup_dirs = []
        if lookup_dirs:
            if isinstance(lookup_dirs, str):
                self.lookup_dirs = [lookup_dirs]
            else:
                self.lookup_dirs = list(lookup_dirs)

    def _find_absolute_path(self, path):
        if os.path.isabs(path):
            return path
        for directory in self.lookup_dirs:
            potential_location = os.path.join(directory, path)
            if os.path.exists(potential_location):
                return str(os.path.abspath(potential_location))
        return path

    def get_source(self, environment, template):
        template = self._find_absolute_path(template)
        return super(FlexibleLoader, self).get_source(environment, template)


class Renderer(object):
    TEMPLATE_NAME = ""

    def __init__(self, product, build_dir, verbose=False):
        self.project_directory = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))

        self.product = product
        self.env_yaml = self.get_env_yaml(build_dir)

        self.built_content_path = (
            "{build_dir}/{product}".format(build_dir=build_dir, product=product))

        self.template_data = dict()
        self.verbose = verbose

    def get_env_yaml(self, build_dir):
        product_yaml = os.path.join(build_dir, self.product, "product.yml")
        build_config_yaml = os.path.join(build_dir, "build_config.yml")
        if not (os.path.exists(product_yaml) and os.path.exists(build_config_yaml)):
            msg = (
                "No product yaml and/or build config found in "
                "'{product_yaml}' and/or '{build_config_yaml}', respectively, please make sure "
                "that you got the product right, and that it is built."
                .format(product_yaml=product_yaml, build_config_yaml=build_config_yaml)
            )
            raise ValueError(msg)
        env_yaml = ssg.environment.open_environment(build_config_yaml, product_yaml)
        return env_yaml

    def _set_rule_relative_definition_location(self, rule):
        rule.relative_definition_location = rule.definition_location.replace(
            self.project_directory, "")

    def _get_template_basedir(self):
        if not self.TEMPLATE_NAME:
            return None
        path_components = os.path.split(self.TEMPLATE_NAME)
        if len(path_components) == 1:
            return None
        return os.path.join(* path_components[:-1])

    def get_result(self):
        subst_dict = self.template_data.copy()
        subst_dict.update(self.env_yaml)
        html_jinja_template = os.path.join(os.path.dirname(__file__), self.TEMPLATE_NAME)
        lookup_dirs = [os.path.join(self.project_directory, "utils")]

        template_basedir = self._get_template_basedir()
        if template_basedir:
            abs_basedir = os.path.join(lookup_dirs[0], template_basedir)
            lookup_dirs.append(abs_basedir)

        ssg.jinja._get_jinja_environment.env.loader = FlexibleLoader(lookup_dirs)
        return ssg.jinja.process_file(html_jinja_template, subst_dict)

    def output_results(self, args):
        if "title" not in self.template_data:
            self.template_data["title"] = args.title
        result = self.get_result()
        if not args.output:
            print(result)
        else:
            dir = os.path.dirname(args.output)
            if not os.path.exists(dir):
                os.makedirs(dir)
            with open(args.output, "wb") as outfile:
                result_for_output = result.encode('utf8', 'replace')
                outfile.write(result_for_output)

    @staticmethod
    def create_parser(description):
        parser = argparse.ArgumentParser(description=description)
        parser.add_argument(
            "product", help="The product to be built")
        parser.add_argument("--build-dir", default="build", help="Path to the build directory")
        parser.add_argument("--title", "-t", default="", help="Title of the document")
        parser.add_argument("--output", help="The filename to generate")
        parser.add_argument("--verbose", action="store_true", default=False)
        return parser