Skip to content

Commit 9c74387

Browse files
authored
Merge pull request #24 from IBM/v6.1
add ConfigManager class
2 parents e253dec + 45260c1 commit 9c74387

File tree

5 files changed

+166
-60
lines changed

5 files changed

+166
-60
lines changed

source/confParser.py

Lines changed: 75 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ def checkTLSsettings(args):
4747
def getSettings(argv):
4848
settings = {}
4949
msg = ''
50+
defaults = ConfigManager().defaults
5051
args, msg = parse_cmd_args(argv)
51-
defaults = parse_defaults_from_config_file()
5252
if args and defaults:
5353
settings = merge_defaults_and_args(defaults, args)
5454
elif args:
@@ -71,38 +71,91 @@ def merge_defaults_and_args(defaults, args):
7171
return brConfig
7272

7373

74-
def parse_defaults_from_config_file(fileName='config.ini'):
75-
'''parse default parameters from a config file'''
76-
defaults = {}
77-
dirname, filename = os.path.split(os.path.abspath(__file__))
78-
conf_file = os.path.join(dirname, fileName)
79-
if os.path.isfile(conf_file):
80-
config = configparser.ConfigParser()
81-
config.optionxform = str
82-
config.read(conf_file)
83-
for sect in config.sections():
84-
for name, value in config.items(sect):
74+
class Singleton(type):
75+
_inst = {}
76+
77+
def __call__(clazz, *args, **kwargs):
78+
if clazz not in clazz._inst:
79+
clazz._inst[clazz] = super(Singleton, clazz).__call__(*args, **kwargs)
80+
return clazz._inst[clazz]
81+
82+
83+
class ConfigManager(object, metaclass=Singleton):
84+
''' A singleton class managing the application configuration defaults '''
85+
86+
def __init__(self):
87+
self.__sectOptions = {}
88+
self.__defaults = {}
89+
self.configFiles = ['config.ini']
90+
91+
@property
92+
def options(self):
93+
if not self.__sectOptions:
94+
self.__sectOptions = self.reload()
95+
return self.__sectOptions
96+
97+
@property
98+
def defaults(self):
99+
if not self.__defaults:
100+
self.__defaults = self.parse_defaults()
101+
return self.__defaults
102+
103+
def reload(self):
104+
options = {}
105+
self.__sectOptions = {}
106+
if self.configFiles:
107+
for config in self.configFiles:
108+
options.update(self.readConfigFile(config))
109+
return options
110+
111+
def readConfigFile(self, fileName):
112+
'''parse config file and store values in a dict {section:{ key: value}}'''
113+
options = {}
114+
dirname, filename = os.path.split(os.path.abspath(__file__))
115+
conf_file = os.path.join(dirname, fileName)
116+
if os.path.isfile(conf_file):
117+
try:
118+
config = configparser.ConfigParser()
119+
config.optionxform = str
120+
config.read(conf_file)
121+
for sect in config.sections():
122+
options[sect] = {}
123+
for name, value in config.items(sect):
124+
if value.isdigit():
125+
value = int(value)
126+
options[sect][name] = value
127+
except Exception as e:
128+
print(f"cannot read config file {fileName} Exception {e}")
129+
else:
130+
print(f"cannot find config file {fileName} in {dirname}")
131+
return options
132+
133+
def parse_defaults(self):
134+
'''parse all sections parameters to a simple key:value dict'''
135+
defaults = {}
136+
for sect_name, sect_values in self.options.items():
137+
for name, value in sect_values.items():
85138
defaults[name] = value
86-
return defaults
139+
return defaults
87140

88141

89142
def parse_cmd_args(argv):
90143
'''parse input parameters'''
91144

92145
parser = argparse.ArgumentParser('python zimonGrafanaIntf.py')
93-
parser.add_argument('-s', '--server', action="store", default='localhost',
94-
help='Host name or ip address of the ZIMon collector (Default: 127.0.0.1) \
146+
parser.add_argument('-s', '--server', action="store", default=None,
147+
help='Host name or ip address of the ZIMon collector (Default from config.ini: 127.0.0.1) \
95148
NOTE: Per default ZIMon does not accept queries from remote machines. \
96149
To run the bridge from outside of the ZIMon collector, you need to modify ZIMon queryinterface settings (\'ZIMonCollector.cfg\')')
97-
parser.add_argument('-P', '--serverPort', action="store", type=int, choices=[9084, 9094], default=9084,
98-
help='ZIMon collector port number (Default: 9084) \
150+
parser.add_argument('-P', '--serverPort', action="store", type=int, choices=[9084, 9094], default=None,
151+
help='ZIMon collector port number (Default from config.ini: 9084) \
99152
NOTE: In some environments, for better bridge performance the usage of the multi-threaded port 9094 could be helpful.\
100153
In this case make sure the \'query2port = \"9094\"\' is enabled in the ZIMon queryinterface settings (\'ZIMonCollector.cfg\')')
101-
parser.add_argument('-l', '--logPath', action="store", default="/var/log/ibm_bridge_for_grafana", help='location path of the log file (Default: /var/log/ibm_bridge_for_grafana')
102-
parser.add_argument('-f', '--logFile', action="store", default="zserver.log", help='Name of the log file (Default: zserver.log')
103-
parser.add_argument('-c', '--logLevel', action="store", type=int, default=15,
104-
help='log level. Available levels: 10 (DEBUG), 15 (MOREINFO), 20 (INFO), 30 (WARN), 40 (ERROR) (Default: 15)')
105-
parser.add_argument('-p', '--port', action="store", type=int, choices=[4242, 8443], default=4242, help='port number listening on for HTTP(S) connections (Default: 4242)')
154+
parser.add_argument('-l', '--logPath', action="store", default=None, help='location path of the log file (Default from config.ini: \'/var/log/ibm_bridge_for_grafana\')')
155+
parser.add_argument('-f', '--logFile', action="store", default=None, help='Name of the log file (Default from config.ini: zserver.log')
156+
parser.add_argument('-c', '--logLevel', action="store", type=int, default=None,
157+
help='log level. Available levels: 10 (DEBUG), 15 (MOREINFO), 20 (INFO), 30 (WARN), 40 (ERROR) (Default from config.ini: 15)')
158+
parser.add_argument('-p', '--port', action="store", type=int, choices=[4242, 8443], default=None, help='port number listening on for HTTP(S) connections (Default from config.ini: 4242)')
106159
parser.add_argument('-t', '--tlsKeyPath', action="store", default=None, help='Directory path of tls privkey.pem and cert.pem file location (Required only for HTTPS port 8443)')
107160
parser.add_argument('-k', '--tlsKeyFile', action="store", default=None, help='Name of TLS key file, f.e.: privkey.pem (Required only for HTTPS port 8443)')
108161
parser.add_argument('-m', '--tlsCertFile', action="store", default=None, help='Name of TLS certificate file, f.e.: cert.pem (Required only for HTTPS port 8443)')

source/config.ini

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ serverPort = 9084
3030
# Directory where the bridge can store logs
3131
logPath = /var/log/ibm_bridge_for_grafana
3232

33-
# log level 10 (DEBUG), 20 (INFO), 30 (WARN), 40 (ERROR) (Default: 20)
34-
logLevel = 20
33+
# log level 10 (DEBUG), 15 (MOREINFO), 20 (INFO), 30 (WARN), 40 (ERROR) (Default: 15)
34+
logLevel = 15
3535

3636
# Log file name (Default: zserver.log)
3737
logFile = zserver.log

tests/test_cli_parser.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44

55

66
def my_setup():
7-
global a, b, c, d, e, f
7+
global a, b, c, d, e, f, g
88
a = ['-p', '8443', '-t', '/etc/my_tls']
99
b = ['-a']
1010
c = ['-a', 'abc']
1111
d = ['-c', '10', '-v', '/opt/registry/certs']
1212
e = ['-c', '10', '-t', '/opt/registry/certs']
1313
f = ['-c', '10', '-s', '9.155.108.199', '-p', '8443', '-t', '/opt/registry/certs', '--tlsKeyFile', 'privkey.pem', '--tlsCertFile', 'cert.pem']
14+
g = ['-p', '4242', '-P', '9084']
1415

1516

1617
def test_case01():
@@ -34,17 +35,19 @@ def test_case03():
3435
assert all(item in elements for item in mandatoryItems)
3536

3637

38+
@with_setup(my_setup)
3739
def test_case04():
38-
args, msg = parse_cmd_args([])
40+
args, msg = parse_cmd_args(g)
3941
result = vars(args)
40-
value = int(result['port'])
41-
assert value == 4242
42+
assert isinstance(result['port'], int)
43+
assert result['port'] == 4242
4244

4345

46+
@with_setup(my_setup)
4447
def test_case05():
45-
args, msg = parse_cmd_args([])
48+
args, msg = parse_cmd_args(g)
4649
result = vars(args)
47-
assert int(result['port']) == 4242 and int(result['serverPort']) == 9084
50+
assert result['port'] == 4242 and result['serverPort'] == 9084
4851

4952

5053
@with_setup(my_setup)

tests/test_configManager.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
from source.confParser import ConfigManager
2+
3+
4+
def test_case01():
5+
cm = ConfigManager()
6+
result = cm.readConfigFile('config.ini')
7+
assert isinstance(result, dict)
8+
9+
10+
def test_case02():
11+
cm = ConfigManager()
12+
result = cm.readConfigFile('config.ini')
13+
assert len(result.keys()) > 0
14+
15+
16+
def test_case03():
17+
cm = ConfigManager()
18+
result = cm.readConfigFile('config.ini')
19+
assert 'tls' in result.keys()
20+
21+
22+
def test_case04():
23+
cm = ConfigManager()
24+
result = cm.readConfigFile('config.ini')
25+
connection = result['connection']
26+
assert len(connection) > 0
27+
assert isinstance(connection, dict)
28+
assert len(connection) > 0
29+
assert 'port' in connection.keys()
30+
31+
32+
def test_case05():
33+
cm = ConfigManager()
34+
result = cm.parse_defaults()
35+
assert isinstance(result, dict)
36+
37+
38+
def test_case06():
39+
cm = ConfigManager()
40+
result = cm.parse_defaults()
41+
assert len(result.keys()) > 0
42+
43+
44+
def test_case07():
45+
cm = ConfigManager()
46+
result = cm.parse_defaults()
47+
result1 = cm.defaults
48+
assert len(result) == len(result1)
49+
50+
51+
def test_case08():
52+
cm = ConfigManager()
53+
result = cm.defaults
54+
elements = list(result.keys())
55+
mandatoryItems = ['port', 'serverPort']
56+
assert all(item in elements for item in mandatoryItems)
57+
58+
59+
def test_case09():
60+
cm = ConfigManager()
61+
result = cm.defaults
62+
value = int(result['port'])
63+
assert value == 4242
64+
65+
66+
def test_case10():
67+
cm = ConfigManager()
68+
result = cm.defaults
69+
assert int(result['port']) == 4242 and int(result['serverPort']) == 9084

tests/test_params.py

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,33 @@
1-
from source.confParser import parse_defaults_from_config_file, merge_defaults_and_args, parse_cmd_args
1+
from source.confParser import ConfigManager, merge_defaults_and_args, parse_cmd_args
22
from nose.tools import with_setup
33

44

55
def my_setup():
66
global a, b, c, d, e
7-
a = parse_defaults_from_config_file()
7+
a = ConfigManager().defaults
88
b, c = parse_cmd_args([])
99
d, e = parse_cmd_args(['-p', '8443', '-t', '/etc/my_tls'])
1010

1111

12+
@with_setup(my_setup)
1213
def test_case01():
13-
result = parse_defaults_from_config_file()
14-
assert isinstance(result, dict)
15-
16-
17-
def test_case02():
18-
result = parse_defaults_from_config_file()
14+
result = merge_defaults_and_args(a, b)
1915
assert len(result.keys()) > 0
20-
21-
22-
def test_case03():
23-
result = parse_defaults_from_config_file()
24-
elements = list(result.keys())
25-
mandatoryItems = ['port', 'serverPort']
26-
assert all(item in elements for item in mandatoryItems)
27-
28-
29-
def test_case04():
30-
result = parse_defaults_from_config_file()
31-
value = int(result['port'])
32-
assert value == 4242
33-
34-
35-
def test_case05():
36-
result = parse_defaults_from_config_file()
37-
assert int(result['port']) == 4242 and int(result['serverPort']) == 9084
16+
assert 'port' in result.keys()
17+
assert 'serverPort' in result.keys()
3818

3919

4020
@with_setup(my_setup)
41-
def test_case06():
21+
def test_case02():
4222
result = merge_defaults_and_args(a, b)
4323
assert len(result.keys()) > 0
44-
assert 'port' in result.keys()
45-
assert 'serverPort' in result.keys()
24+
assert 'logLevel' in result.keys()
25+
assert isinstance(result.get('logLevel'), int)
26+
assert result.get('logLevel') == 15
4627

4728

4829
@with_setup(my_setup)
49-
def test_case07():
30+
def test_case03():
5031
result = merge_defaults_and_args(a, d)
5132
assert len(result.keys()) > 0
5233
assert 'port' in result.keys()

0 commit comments

Comments
 (0)