Newer
Older
#!/usr/bin/env python3
"""Convert a template mapfile config to a full config.
We do this rendering when the container is started to allow for complete
control per mapserver instance (even though there is usually only one).
"""
import itertools
import os
import sys
import jinja2
import yaml
sectors_filter = os.getenv("WMS_SECTORS", "")
if sectors_filter:
sectors_filter = sectors_filter.split(" ")
products_filter = os.getenv("WMS_PRODUCTS", "")
if products_filter:
products_filter = products_filter.split(" ")
satellites_filter = os.getenv("WMS_PLATFORMS", "")
if satellites_filter:
satellites_filter = satellites_filter.split(" ")
layer_base_dir = os.environ['LAYER_BASE_DIR']
def _get_connect_str():
pw_filename = "__POSTGRES_PASSWORD_FILE__"
connect_str = "host=__POSTGRES_HOST__ " \
"port=__POSTGRES_PORT__ " \
"dbname=__POSTGRES_DBNAME__ " \
"user=__POSTGRES_USER__"
if not os.path.isfile(pw_filename) or '__' in connect_str:
print(pw_filename, os.path.isfile(pw_filename), connect_str)
raise ValueError("Backend has not been configured properly "
"and doesn't know how to communicate with the database. "
"Please contact site administrator.")
with open(pw_filename, 'r') as pw_file:
password = pw_file.read().strip()
connect_str += " password={}".format(password)
return connect_str
def main():
import argparse
parser = argparse.ArgumentParser(description="Render mapfile template to complete mapfile config.")
parser.add_argument("product_yaml_config",
help="GeoSphere YAML configuration file. Matches the YAML used by GeoSphere API, "
"but not all the information may be used.")
parser.add_argument("template_fn",
help="Template XML file to render")
parser.add_argument('output_pattern',
help='Format string for each output mapfiles. Should be per-sector per-processing level.')
# Check if this script was properly sed'd with database information
connect_params = _get_connect_str() if "__" not in "__POSTGRES_HOST__" else ""
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
with open(args.product_yaml_config) as product_yaml:
geosphere_config = yaml.load(product_yaml, Loader=yaml.SafeLoader)
for template_info in template_info_from_config_and_db_info(geosphere_config, connect_params):
output_fn = args.output_pattern.format(**template_info)
render_mapfile_template_with_template_info(args.template_fn, output_fn, template_info)
def template_info_from_config_and_db_info(geosphere_config: dict, connect_params: str):
for satellite_info in geosphere_config["satellites"]:
if satellites_filter and satellite_info["identifier"] not in satellites_filter:
continue
for instrument_info in satellite_info["instruments"]:
for sector_info in instrument_info["sectors"]:
if sectors_filter and sector_info["identifier"] not in sectors_filter:
continue
projection_info = projection_info_for_id(geosphere_config["projections"], sector_info["projection_id"])
product_infos_groups = per_processing_level_product_infos(sector_info["products"])
for processing_level, product_infos_for_plevel in product_infos_groups:
# print(len(sector_info["products"]))
# product_infos_for_plevel = list(product_infos_for_plevel)
# print(processing_level, product_infos_for_plevel)
product_infos = filter_products(product_infos_for_plevel, products_filter)
template_info = {
'sector_info': sector_info,
'satellite_info': satellite_info,
'instrument_info': instrument_info,
'processing_level': processing_level,
'products': product_infos,
'layer_base_dir': layer_base_dir,
'projection': f"init=epsg:{projection_info['epsg_code']}",
'epsg_code': str(projection_info["epsg_code"]),
'postgis_connection_params': connect_params,
'postgis_geom_column': 'bbox_geometry',
}
yield template_info
def projection_info_for_id(projection_infos, projection_id):
return [proj_info for proj_info in projection_infos if proj_info["identifier"] == projection_id][0]
def per_processing_level_product_infos(sector_product_infos):
"""Split a list of product information dictionaries into groups by ``processing_level``."""
yield from itertools.groupby(sector_product_infos, key=lambda product_info: product_info["processing_level"])
def filter_products(product_infos, product_identifiers_to_keep):
if not product_identifiers_to_keep:
return product_infos
return [product_info for product_info in product_infos if
product_info["identifier"] in product_identifiers_to_keep]
def render_mapfile_template_with_template_info(template_fn, output_fn, template_info):
with open(template_fn, 'r') as tmpl_file, open(output_fn, 'w') as mapfile:
template = jinja2.Template(tmpl_file.read())
mapfile.write(template.render(template_info, env=os.environ))