Home | History | Annotate | Line # | Download | only in isctest
      1 #!/usr/bin/python3
      2 
      3 # Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      4 #
      5 # SPDX-License-Identifier: MPL-2.0
      6 #
      7 # This Source Code Form is subject to the terms of the Mozilla Public
      8 # License, v. 2.0.  If a copy of the MPL was not distributed with this
      9 # file, you can obtain one at https://mozilla.org/MPL/2.0/.
     10 #
     11 # See the COPYRIGHT file distributed with this work for additional
     12 # information regarding copyright ownership.
     13 
     14 from dataclasses import dataclass
     15 from pathlib import Path
     16 from typing import Any, Dict, Optional, Union
     17 
     18 import jinja2
     19 
     20 from .log import debug
     21 from .vars import ALL
     22 
     23 
     24 class TemplateEngine:
     25     """
     26     Engine for rendering jinja2 templates in system test directories.
     27     """
     28 
     29     def __init__(self, directory: Union[str, Path], env_vars=ALL):
     30         """
     31         Initialize the template engine for `directory`, optionally overriding
     32         the `env_vars` that will be used when rendering the templates (defaults
     33         to the environment variables set by the pytest runner).
     34         """
     35         self.directory = Path(directory)
     36         self.env_vars = dict(env_vars)
     37         self.j2env = jinja2.Environment(
     38             loader=jinja2.FileSystemLoader(str(self.directory)),
     39             undefined=jinja2.StrictUndefined,
     40             variable_start_string="@",
     41             variable_end_string="@",
     42         )
     43 
     44     def render(
     45         self,
     46         output: str,
     47         data: Optional[Dict[str, Any]] = None,
     48         template: Optional[str] = None,
     49     ) -> None:
     50         """
     51         Render `output` file from jinja `template` and fill in the `data`. The
     52         `template` defaults to *.j2.manual or *.j2 file. The environment
     53         variables which the engine was initialized with are also filled in. In
     54         case of a variable name clash, `data` has precedence.
     55         """
     56         if template is None:
     57             template = f"{output}.j2.manual"
     58             if not Path(template).is_file():
     59                 template = f"{output}.j2"
     60         if not Path(template).is_file():
     61             raise RuntimeError('No jinja2 template found for "{output}"')
     62 
     63         if data is None:
     64             data = self.env_vars
     65         else:
     66             data = {**self.env_vars, **data}
     67 
     68         debug("rendering template `%s` to file `%s`", template, output)
     69         stream = self.j2env.get_template(template).stream(data)
     70         stream.dump(output, encoding="utf-8")
     71 
     72     def render_auto(self, data: Optional[Dict[str, Any]] = None):
     73         """
     74         Render all *.j2 templates with default (and optionally the provided)
     75         values and write the output to files without the .j2 extensions.
     76         """
     77         templates = [
     78             str(filepath.relative_to(self.directory))
     79             for filepath in self.directory.rglob("*.j2")
     80         ]
     81         for template in templates:
     82             self.render(template[:-3], data)
     83 
     84 
     85 @dataclass
     86 class Nameserver:
     87     name: str
     88     ip: str
     89 
     90 
     91 @dataclass
     92 class Zone:
     93     name: str
     94     filename: str
     95     ns: Nameserver
     96     type: str = "primary"
     97 
     98 
     99 @dataclass
    100 class TrustAnchor:
    101     domain: str
    102     type: str
    103     contents: str
    104