-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathconfig.py
159 lines (140 loc) · 6.47 KB
/
config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import logging
import os.path
from os.path import expanduser, normpath, dirname, abspath
import yaml
import re
import boto3
CONFIG_BROKER = {}
CONFIG_SERVICES = {}
CONFIG_DB = {}
CONFIG_LOGGING = {}
CONFIG_CATEGORIES = {"broker": CONFIG_BROKER, "services": CONFIG_SERVICES, "db": CONFIG_DB,
"logging": CONFIG_LOGGING}
# set the location of the Data Broker config files
CONFIG_PATH = os.path.join(dirname(abspath(__file__)), 'config.yml')
if "env" in os.environ:
env = os.environ["env"]
else:
env = "local"
ENV_PATH = os.path.join(dirname(abspath(__file__)), '{}_config.yml'.format(env))
path_list = [CONFIG_PATH, ENV_PATH]
# set the location of the Alembic config file
ALEMBIC_PATH = os.path.join(dirname(abspath(__file__)), 'alembic.ini')
MIGRATION_PATH = os.path.join(dirname(abspath(__file__)), 'migrations')
for config_path in path_list:
try:
with open(config_path) as c:
# Default to empty dictionary if file is empty
CONFIG_ALL = yaml.load(c, Loader=yaml.FullLoader) or {}
except IOError:
raise IOError('Error reading a config file. Please make sure this file exists'
' before starting the Data Broker: {}'.format(config_path))
for category_name in CONFIG_CATEGORIES:
CONFIG_CATEGORIES[category_name].update(CONFIG_ALL.get(category_name, {}))
# Override any values with secrets if applicable
# Must occur before additional local/remote setup
if CONFIG_BROKER['use_aws'] is True or CONFIG_BROKER['use_aws'] == "true":
# Parameter Store
env_group = 'prod' if env == 'prod' else 'nonprod'
secrets_param_name = f'/{env_group}/broker/broker_{env}_secrets'
ssm_client = boto3.client('ssm', region_name=CONFIG_BROKER['aws_region'])
secrets_yaml_param = ssm_client.get_parameter(Name=secrets_param_name, WithDecryption=True)
SECRETS_CONFIG = yaml.load(secrets_yaml_param['Parameter']['Value'], Loader=yaml.FullLoader) or {}
else:
# Local Secrets
SECRET_PATH = os.path.join(dirname(abspath(__file__)), '{}_secrets.yml'.format(env))
try:
with open(SECRET_PATH) as c:
# Default to empty dictionary if file is empty
SECRETS_CONFIG = yaml.load(c, Loader=yaml.FullLoader) or {}
except IOError:
raise IOError('Error reading a config file. Please make sure this file exists'
' before starting the Data Broker: {}'.format(SECRET_PATH))
if SECRETS_CONFIG:
for category_name in CONFIG_CATEGORIES:
CONFIG_CATEGORIES[category_name].update(SECRETS_CONFIG.get(category_name, {}))
# Get path to installation
CONFIG_BROKER['path'] = dirname(dirname(abspath(__file__)))
# for backward-compatibility, differentiate between local runs and AWS
if CONFIG_BROKER['use_aws'] is True or CONFIG_BROKER['use_aws'] == "true":
CONFIG_BROKER['local'] = False
# AWS flag is on, so make sure all needed AWS info is present
required_aws_keys = ['aws_bucket', 'aws_region']
for k in required_aws_keys:
try:
CONFIG_BROKER[k]
except KeyError:
raise KeyError('Config error: use_aws is True, but the {} key is missing from the config.yml file'.
format(k))
if not CONFIG_BROKER[k]:
raise ValueError('Config error: use_aws is True but {} value is missing'.format(k))
else:
CONFIG_BROKER['local'] = True
CONFIG_BROKER['aws_bucket'] = None
CONFIG_BROKER['aws_region'] = None
# if not using AWS and no error report path specified,
# default to `data_act_broker` in user's home dir
error_report_path = CONFIG_SERVICES['error_report_path']
if not error_report_path:
error_report_path = os.path.join(expanduser('~'), 'data_act_broker')
normpath(error_report_path)
CONFIG_SERVICES['error_report_path'] = error_report_path
storage_path = CONFIG_BROKER['d_file_storage_path']
if storage_path[-1] != os.path.sep:
CONFIG_BROKER['d_file_storage_path'] = "".join([storage_path, os.path.sep])
error_storage_path = CONFIG_SERVICES['error_report_path']
if error_storage_path[-1] != os.path.sep:
CONFIG_SERVICES['error_report_path'] = "".join([error_storage_path, os.path.sep])
# if no broker file path specified,
# default to `data_act_broker` in user's home dir
broker_files = CONFIG_BROKER['broker_files']
if not broker_files:
broker_files = os.path.join(expanduser('~'), 'data_act_broker')
elif len(os.path.splitext(broker_files)[1]):
# if config's broker_files is set to a actual filename
# just use the directory
broker_files = os.path.split(broker_files)[0]
normpath(broker_files)
if broker_files[-1] != os.path.sep:
broker_files += os.path.sep
CONFIG_BROKER['broker_files'] = broker_files
# normalize logging path, if given
log_path = CONFIG_LOGGING['log_files']
if log_path:
CONFIG_LOGGING['log_files'] = normpath(log_path)
# we don't want http:// or ports in the host variables
CONFIG_SERVICES['broker_api_host'] = re.sub(
'http://|:(.*)', '', CONFIG_SERVICES['broker_api_host'])
CONFIG_SERVICES['validator_host'] = re.sub(
'http://|:(.*)', '', CONFIG_SERVICES['validator_host'])
# if hosts in config file are set to 0.0.0.0, override to
# 127.0.0.1 for cross-platform compatibility
if env != "local" and CONFIG_SERVICES['broker_api_host'] == '0.0.0.0':
CONFIG_SERVICES['broker_api_host'] = '127.0.0.1'
if CONFIG_SERVICES["broker_api_port"] == 443:
# Use https
CONFIG_SERVICES["protocol"] = "https"
else:
CONFIG_SERVICES["protocol"] = "http"
# Log some values from config
log_message = ""
if "values_to_log" in CONFIG_LOGGING:
# If no values specified, don't do logging
for category_yaml_name in CONFIG_LOGGING["values_to_log"]:
category = CONFIG_CATEGORIES[category_yaml_name]
category_message = "### {}".format(category_yaml_name)
for key in CONFIG_LOGGING["values_to_log"][category_yaml_name]:
value = category.get(key, "Value not provided in config")
category_message = "{}, {}: {}".format(category_message, key, value)
log_message = " ".join([log_message, category_message])
# Log config values along with warnings for missing files
if log_message:
# Logging is not configured yet; create a console logger to print this
# message
_logger = logging.getLogger('config-printer')
_logger.setLevel(logging.INFO)
_logger.addHandler(logging.FileHandler(os.path.join(
CONFIG_LOGGING['log_files'], 'info.log')))
_logger.info(log_message)
# TODO: error-handling for db config?
# TODO: type checking and fixing for int stuff like ports?