blob: 2fbbaa9e45f115803d4f7e94029562644c7dc827 [file] [log] [blame]
garciadeblas3a5d2042024-11-21 01:12:53 +01001#!/usr/bin/python3
2# Copyright ETSI Contributors and Others.
3# All Rights Reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License"); you may
6# not use this file except in compliance with the License. You may obtain
7# a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14# License for the specific language governing permissions and limitations
15# under the License.
16
17
18# generate_osm_test.py --config test_config.yaml
19
20import argparse
21import logging
22import os
23import yaml
24
25# from jinja2 import Environment, FileSystemLoader, select_autoescape
26from jinja2 import Template
27
28
29####################################
30# Global functions
31####################################
32def set_logger(verbose):
33 global logger
34 log_format_simple = "%(levelname)s %(message)s"
35 log_format_complete = "%(asctime)s %(levelname)s %(name)s %(filename)s:%(lineno)s %(funcName)s(): %(message)s"
36 log_formatter_simple = logging.Formatter(
37 log_format_simple, datefmt="%Y-%m-%dT%H:%M:%S"
38 )
39 handler = logging.StreamHandler()
40 handler.setFormatter(log_formatter_simple)
41 logger = logging.getLogger("generate_osm_test")
42 logger.setLevel(level=logging.WARNING)
43 logger.addHandler(handler)
44 if verbose == 1:
45 logger.setLevel(level=logging.INFO)
46 elif verbose > 1:
47 log_formatter = logging.Formatter(
48 log_format_complete, datefmt="%Y-%m-%dT%H:%M:%S"
49 )
50 handler.setFormatter(log_formatter)
51 logger.setLevel(level=logging.DEBUG)
52
53
54def exit_with_error(message, code=1):
55 logger.error(message)
56 exit(code)
57
58
59def render_template(template_file, test_data, output_file=None):
60 logger.info(f"Rendering {template_file} with test data")
61
62 # Load Jinja template
63 with open(template_file, "r") as template_stream:
64 template = Template(template_stream.read())
65
66 # Render template with test_data and store it in output_file
67 output = template.render(test_data)
68 if output_file:
69 if os.path.exists(output_file):
70 exit_with_error(
71 f"Output file '{output_file}' already exists. Use a different filename or remove it."
72 )
73 with open(output_file, "w") as output_stream:
74 output_stream.write(output)
75 else:
76 print(output)
77
78
79def validate_data(test_data):
80 required_keys = {"nspkg", "ns"}
81 missing_keys = required_keys - test_data.keys()
82 if missing_keys:
83 logger.error(f"Missing required keys in YAML: {', '.join(missing_keys)}")
84 raise ValueError(f"Invalid test data structure: missing keys {missing_keys}")
85
86
87def complete_data(test_data):
88 nspkg_indexes = {nspkg["name"]: i + 1 for i, nspkg in enumerate(test_data["nspkg"])}
89 ns_indexes = {ns["name"]: i + 1 for i, ns in enumerate(test_data["ns"])}
90 for ns in test_data["ns"]:
91 if ns["nspkg"] not in nspkg_indexes:
92 logger.error(
93 f"nspkg '{ns['nspkg']}' referenced in 'ns' not found in 'nspkg'"
94 )
95 raise ValueError(f"Invalid nspkg name: {ns['nspkg']}")
96 ns["nspkg_index"] = nspkg_indexes[ns["nspkg"]]
97 for vnf in test_data["vnf"]:
98 if vnf["ns"] not in ns_indexes:
99 logger.error(f"ns '{vnf['ns']}' referenced in 'vnf' not found in 'ns'")
100 raise ValueError(f"Invalid ns name: {vnf['ns']}")
101 vnf["ns_index"] = ns_indexes[vnf["ns"]]
102
103
104####################################
105# Main
106####################################
107if __name__ == "__main__":
108 # Argument parse
109 parser = argparse.ArgumentParser(
110 description="Generate OSM tests from YAML configuration file."
111 )
112 parser.add_argument(
113 "-v", "--verbose", action="count", default=0, help="increase output verbosity"
114 )
115 # parser.add_argument("--basedir", default=".", help="basedir for the test")
116 parser.add_argument(
117 "--config", required=True, help="yaml configuration file to create the test"
118 )
119 parser.add_argument(
120 "--template",
121 default="test_template.j2",
122 help="template file for rendering the test (default: test_template.j2)",
123 )
124 parser.add_argument(
125 "--output", default=None, help="output file (default: standard output)"
126 )
127 args = parser.parse_args()
128
129 # Calculate paths relative to the script directory
130 script_dir = os.path.dirname(os.path.abspath(__file__))
131 config_path = os.path.abspath(args.config)
132 template_path = os.path.join(script_dir, args.template)
133
134 # Initialize logger
135 set_logger(args.verbose)
136
137 # Load test_data
138 try:
139 with open(config_path, "r") as yaml_stream:
140 test_data = yaml.safe_load(yaml_stream)
141 except FileNotFoundError:
142 exit_with_error(f"Configuration file '{args.config}' not found.")
143 except yaml.YAMLError as e:
144 exit_with_error(f"Error parsing YAML file '{args.config}': {e}")
145 validate_data(test_data)
146 complete_data(test_data)
147 logger.debug(f"Test data:\n{yaml.safe_dump(test_data)}")
148 if not os.path.exists(template_path):
149 exit_with_error(f"Template file '{template_path}' not found.")
150 render_template(template_path, test_data, args.output)