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
|
#!/usr/bin/python3
# Copyright 2021 Michal Arbet
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import logging
import os
import yaml
# Default paths
PROXYSQL_CONFIG_DIR = "/etc/proxysql"
PROXYSQL_CONFIG = "/etc/proxysql.cnf"
# Logging
log_format = '%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s'
logging.basicConfig(format=log_format,
datefmt='%H:%M:%S',
level=logging.DEBUG)
LOG = logging.getLogger("proxysql_config_sync")
class ProxySQLConfig:
def __init__(self, conf_dir, conf_file):
self.configs = dict()
self.config = dict()
self.configs['global'] = "{}/proxysql.yaml".format(conf_dir)
self.configs['users'] = "{}/users".format(conf_dir)
self.configs['rules'] = "{}/rules".format(conf_dir)
self.conf_file = conf_file
self._load_config()
def _load_config(self):
users = dict()
rules = dict()
for cfg, path in self.configs.items():
if not os.path.isdir(path):
with open(path) as config_file:
self.config.update(
yaml.safe_load(config_file))
else:
users['mysql_users'] = list()
rules['mysql_query_rules'] = list()
user_paths = [os.path.join(self.configs['users'], f)
for f in os.listdir(self.configs['users'])]
rule_paths = [os.path.join(self.configs['rules'], f)
for f in os.listdir(self.configs['rules'])]
for user_conf in user_paths:
with open(user_conf) as config_file:
tmp_users = yaml.safe_load(config_file)
for i in tmp_users['mysql_users']:
users['mysql_users'].append(i)
self.config.update(users)
for rule_conf in rule_paths:
with open(rule_conf) as config_file:
tmp_rules = yaml.safe_load(config_file)
for i in tmp_rules['mysql_query_rules']:
rules['mysql_query_rules'].append(i)
self.config.update(rules)
self._sanity()
def _sanity(self):
self._users_sanity()
self._rules_sanity()
def _users_sanity(self):
users_added = list()
users = list()
for user in self.config['mysql_users']:
if user['username'] not in users_added:
users_added.append(user['username'])
users.append(user)
else:
LOG.warning("User {} already exist, ignoring."
.format(user['username']))
self.config['mysql_users'] = users
def _rules_sanity(self):
rules_added = list()
rules = list()
rule_id = 1
for rule in self.config['mysql_query_rules']:
if rule['schemaname'] not in rules_added:
rules_added.append(rule['schemaname'])
rule['rule_id'] = rule_id
rules.append(rule)
rule_id += 1
else:
LOG.warning("Rule witch schemaname {} already exist, ignoring."
.format(rule['schemaname']))
self.config['mysql_query_rules'] = rules
def _write_dict(self, key, value):
if not isinstance(value, list):
value = [value]
with open(self.conf_file, "a+") as f:
if key:
f.write("{} =\n".format(key))
for i in range(len(value)):
f.write(" {\n")
for k, v in value[i].items():
if isinstance(v, str):
v = '"{}"'.format(v)
f.write(" {} = {}\n".format(k, v))
if i == len(value)-1:
f.write(" }\n")
else:
f.write(" },\n")
def _write_list(self, key, values):
with open(self.conf_file, "a+") as f:
f.write("{} =\n".format(key))
f.write("(\n")
self._write_dict(key=None, value=values)
with open(self.conf_file, "a+") as f:
f.write(")\n")
def _write(self, key, value):
with open(self.conf_file, "a+") as f:
if isinstance(value, str):
value = '"{}"'.format(value)
f.write("{} = {}\n".format(key, value))
def write_config(self):
LOG.info("Writing config to {}".format(self.conf_file))
with open(self.conf_file, 'wb') as f:
pass
for k, v in self.config.items():
if isinstance(v, dict):
self._write_dict(k, v)
elif isinstance(v, list):
self._write_list(k, v)
else:
self._write(k, v)
if __name__ == "__main__":
config = ProxySQLConfig(PROXYSQL_CONFIG_DIR, PROXYSQL_CONFIG)
config.write_config()
|