2 ###############################################################################
3 # Copyright (c) 2016 Ericsson AB and others.
4 # peter.barabas@ericsson.com
5 # All rights reserved. This program and the accompanying materials
6 # are made available under the terms of the Apache License, Version 2.0
7 # which accompanies this distribution, and is available at
8 # http://www.apache.org/licenses/LICENSE-2.0
9 ###############################################################################
26 class Templater(object):
27 def __init__(self, base_file, template_file, output_file):
28 self.template_file = template_file
29 self.output_file = output_file
30 self.base = self.load_yaml(base_file)
32 def load_yaml(self, filename):
34 with io.open(filename) as yaml_file:
35 return yaml.load(yaml_file)
36 except Exception as error:
37 err('Error opening YAML file: %s' % error)
39 def save_yaml(self, filename, content):
41 with io.open(filename, 'w') as yaml_file:
42 yaml_file.write(content)
43 except Exception as error:
44 err('Error writing YAML file: %s' % error)
46 def get_indent(self, line):
47 return len(line) - len(line.lstrip(' '))
49 def format_fragment(self, fragment, indent):
53 for line in fragment.splitlines():
54 # Skip indenting the first line as it is already indented
59 line = ' ' * indent + line + '\n'
63 return result.rstrip('\n')
65 def format_substitution(self, string):
66 if isinstance(string, basestring):
69 return yaml.dump(string, default_flow_style=False)
71 def parse_interface_tag(self, tag):
72 # Remove 'interface(' prefix, trailing ')' and split arguments
73 args = tag[len('interface('):].rstrip(')').split(',')
75 if len(args) == 1 and not args[0]:
76 err('No arguments for interface().')
77 elif len(args) == 2 and (not args[0] or not args[1]):
78 err('Empty argument for interface().')
80 err('Too many arguments for interface().')
84 def get_interface_from_network(self, interfaces, network):
85 nics = self.base[interfaces]
87 if network in nics[nic]:
90 err('Network not found: %s' % network)
92 def get_role_interfaces(self, role):
93 nodes = self.base['nodes']
95 if role in node['role']:
96 return node['interfaces']
98 err('Role not found: %s' % role)
100 def lookup_interface(self, args):
101 nodes = self.base['nodes']
104 interfaces = nodes[0]['interfaces']
106 interfaces = self.get_role_interfaces(args[1])
108 return self.get_interface_from_network(interfaces, args[0])
110 def parse_include_tag(self, tag):
111 # Remove 'include(' prefix and trailing ')'
112 filename = tag[len('include('):].rstrip(')')
115 err('No argument for include().')
119 def include_file(self, filename):
120 fragment = self.load_yaml(filename)
121 return yaml.dump(fragment, default_flow_style=False)
123 def parse_tag(self, tag, indent):
126 if 'interface(' in tag:
127 args = self.parse_interface_tag(tag)
128 fragment = self.lookup_interface(args)
129 elif 'include(' in tag:
130 filename = self.parse_include_tag(tag)
131 fragment = self.include_file(filename)
133 path = tag.split(DELIMITER)
137 fragment = fragment.get(i)
139 err('Error: key "%s" does not exist in base YAML file' % i)
141 fragment = self.format_substitution(fragment)
143 return self.format_fragment(fragment, indent)
148 regex = re.compile(re.escape(TAG_START) + r'([a-z].+)' + re.escape(TAG_END),
150 with io.open(self.template_file) as f:
152 indent = self.get_indent(line)
153 result += re.sub(regex,
154 lambda match: self.parse_tag(match.group(1), indent),
157 self.save_yaml(self.output_file, result)
160 def parse_arguments():
161 description = '''Process 'template_file' using 'base_file' as source for
162 template variable substitution and write the results to 'output_file'.'''
164 parser = ArgParser(prog='python %s' % __file__,
165 description=description)
166 parser.add_argument('base_file',
167 help='Base YAML filename')
168 parser.add_argument('template_file',
169 help='Fragment filename')
170 parser.add_argument('output_file',
171 help='Output filename')
173 args = parser.parse_args()
174 return(args.base_file, args.template_file, args.output_file)
178 base_file, template_file, output_file = parse_arguments()
180 templater = Templater(base_file, template_file, output_file)
184 if __name__ == '__main__':