Merge "Remove redundant CLI arguments for neutron-db-manage"
[apex-tripleo-heat-templates.git] / tools / process-templates.py
1 #!/usr/bin/env python
2 #    Licensed under the Apache License, Version 2.0 (the "License"); you may
3 #    not use this file except in compliance with the License. You may obtain
4 #    a copy of the License at
5 #
6 #         http://www.apache.org/licenses/LICENSE-2.0
7 #
8 #    Unless required by applicable law or agreed to in writing, software
9 #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11 #    License for the specific language governing permissions and limitations
12 #    under the License.
13
14 import argparse
15 import jinja2
16 import os
17 import six
18 import sys
19 import yaml
20
21
22 def parse_opts(argv):
23     parser = argparse.ArgumentParser(
24         description='Configure host network interfaces using a JSON'
25         ' config file format.')
26     parser.add_argument('-p', '--base_path', metavar='BASE_PATH',
27                         help="""base path of templates to process.""",
28                         default='.')
29     parser.add_argument('-r', '--roles-data', metavar='ROLES_DATA',
30                         help="""relative path to the roles_data.yaml file.""",
31                         default='roles_data.yaml')
32     parser.add_argument('--safe',
33                         action='store_true',
34                         help="""Enable safe mode (do not overwrite files).""",
35                         default=False)
36     opts = parser.parse_args(argv[1:])
37
38     return opts
39
40
41 def _j2_render_to_file(j2_template, j2_data, outfile_name=None,
42                        overwrite=True):
43     yaml_f = outfile_name or j2_template.replace('.j2.yaml', '.yaml')
44     print('rendering j2 template to file: %s' % outfile_name)
45
46     if not overwrite and os.path.exists(outfile_name):
47         print('ERROR: path already exists for file: %s' % outfile_name)
48         sys.exit(1)
49
50     try:
51         # Render the j2 template
52         template = jinja2.Environment().from_string(j2_template)
53         r_template = template.render(**j2_data)
54     except jinja2.exceptions.TemplateError as ex:
55         error_msg = ("Error rendering template %s : %s"
56                      % (yaml_f, six.text_type(ex)))
57         print(error_msg)
58         raise Exception(error_msg)
59     with open(outfile_name, 'w') as out_f:
60         out_f.write(r_template)
61
62
63 def process_templates(template_path, role_data_path, overwrite):
64
65     with open(role_data_path) as role_data_file:
66         role_data = yaml.safe_load(role_data_file)
67
68     j2_excludes_path = os.path.join(template_path, 'j2_excludes.yaml')
69     with open(j2_excludes_path) as role_data_file:
70         j2_excludes = yaml.safe_load(role_data_file)
71
72     role_names = [r.get('name') for r in role_data]
73     r_map = {}
74     for r in role_data:
75         r_map[r.get('name')] = r
76     excl_templates = ['%s/%s' % (template_path, e)
77                       for e in j2_excludes.get('name')]
78
79     if os.path.isdir(template_path):
80         for subdir, dirs, files in os.walk(template_path):
81             for f in files:
82                 file_path = os.path.join(subdir, f)
83                 # We do two templating passes here:
84                 # 1. *.role.j2.yaml - we template just the role name
85                 #    and create multiple files (one per role)
86                 # 2. *.j2.yaml - we template with all roles_data,
87                 #    and create one file common to all roles
88                 if f.endswith('.role.j2.yaml'):
89                     print("jinja2 rendering role template %s" % f)
90                     with open(file_path) as j2_template:
91                         template_data = j2_template.read()
92                         print("jinja2 rendering roles %s" % ","
93                               .join(role_names))
94                         for role in role_names:
95                             j2_data = {'role': role}
96                             # (dprince) For the undercloud installer we don't
97                             # want to have heat check nova/glance API's
98                             if r_map[role].get('disable_constraints', False):
99                                 j2_data['disable_constraints'] = True
100                             out_f = "-".join(
101                                 [role.lower(),
102                                  os.path.basename(f).replace('.role.j2.yaml',
103                                                              '.yaml')])
104                             out_f_path = os.path.join(subdir, out_f)
105                             if not (out_f_path in excl_templates):
106                                 _j2_render_to_file(template_data, j2_data,
107                                                    out_f_path, overwrite)
108                             else:
109                                 print('skipping rendering of %s' % out_f_path)
110                 elif f.endswith('.j2.yaml'):
111                     print("jinja2 rendering normal template %s" % f)
112                     with open(file_path) as j2_template:
113                         template_data = j2_template.read()
114                         j2_data = {'roles': role_data}
115                         out_f = file_path.replace('.j2.yaml', '.yaml')
116                         _j2_render_to_file(template_data, j2_data, out_f,
117                                            overwrite)
118
119     else:
120         print('Unexpected argument %s' % template_path)
121
122 opts = parse_opts(sys.argv)
123
124 role_data_path = os.path.join(opts.base_path, opts.roles_data)
125
126 process_templates(opts.base_path, role_data_path, (not opts.safe))