Coverage for cfg_checker/common/other.py : 26%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import os
2import re
3import subprocess
5from cfg_checker.common.const import all_roles_map, uknown_code
6from cfg_checker.common.exception import ConfigException
8pkg_dir = os.path.dirname(__file__)
9pkg_dir = os.path.join(pkg_dir, os.pardir, os.pardir)
10pkg_dir = os.path.normpath(pkg_dir)
11pkg_dir = os.path.abspath(pkg_dir)
14def shell(command):
15 _ps = subprocess.Popen(
16 command.split(),
17 stdout=subprocess.PIPE
18 ).communicate()[0].decode()
20 return _ps
23def merge_dict(source, destination):
24 """
25 Dict merger, thanks to vincent
26 http://stackoverflow.com/questions/20656135/python-deep-merge-dictionary-data
28 >>> a = { 'first' : { 'all_rows' : { 'pass' : 'dog', 'number' : '1' } } }
29 >>> b = { 'first' : { 'all_rows' : { 'fail' : 'cat', 'number' : '5' } } }
30 >>> merge(b, a) == {
31 'first': {
32 'all_rows': {
33 'pass': 'dog',
34 'fail': 'cat',
35 'number': '5'
36 }
37 }
38 }
39 True
40 """
41 for key, value in source.items():
42 if isinstance(value, dict):
43 # get node or create one
44 node = destination.setdefault(key, {})
45 merge_dict(value, node)
46 else:
47 destination[key] = value
49 return destination
52class Utils(object):
53 @staticmethod
54 def validate_name(fqdn, message=False):
55 """
56 Function that tries to validate node name.
57 Checks if code contains letters, has '.' in it,
58 roles map contains code's role
60 :param fqdn: node FQDN name to supply for the check
61 :param message: True if validate should return error check message
62 :return: False if checks failed, True if all checks passed
63 """
64 _message = "# Validation passed"
66 def _result():
67 return (True, _message) if message else True
69 # node role code checks
70 _code = re.findall(r"[a-zA-Z]+", fqdn.split('.')[0])
71 if len(_code) > 0:
72 if _code[0] in all_roles_map:
73 return _result()
74 else:
75 # log warning here
76 _message = "# Node code is unknown, '{}'. " \
77 "# Please, update map".format(_code)
78 else:
79 # log warning here
80 _message = "# Node name is invalid, '{}'".format(fqdn)
82 # put other checks here
84 # output result
85 return _result()
87 @staticmethod
88 def node_string_to_list(node_string):
89 # supplied var should contain node list
90 # if there is no ',' -> use space as a delimiter
91 if node_string is not None:
92 if node_string.find(',') < 0:
93 return node_string.split(' ')
94 else:
95 return node_string.split(',')
96 else:
97 return []
99 def get_node_code(self, fqdn):
100 # validate
101 _isvalid, _message = self.validate_name(fqdn, message=True)
102 _code = re.findall(
103 r"[a-zA-Z]+?(?=(?:[0-9]+$)|(?:\-+?)|(?:\_+?)|$)",
104 fqdn.split('.')[0]
105 )
106 # check if it is valid and raise if not
107 if _isvalid:
108 # try to match it with ones in map
109 _c = _code[0]
110 match = any([r in _c for r in all_roles_map.keys()])
111 if match:
112 # no match, try to find it
113 match = False
114 for r in all_roles_map.keys():
115 _idx = _c.find(r)
116 if _idx > -1:
117 _c = _c[_idx:]
118 match = True
119 break
120 if match:
121 return _c
122 else:
123 return uknown_code
124 else:
125 return uknown_code
126 else:
127 raise ConfigException(_message)
129 def get_nodes_list(self, env, nodes_list):
130 _list = []
131 if env is None:
132 # nothing supplied, use the one in repo
133 try:
134 if not nodes_list:
135 return []
136 with open(os.path.join(pkg_dir, nodes_list)) as _f:
137 _list.extend(_f.read().splitlines())
138 except IOError as e:
139 raise ConfigException("# Error while loading file, '{}': "
140 "{}".format(e.filename, e.strerror))
141 else:
142 _list.extend(self.node_string_to_list(env))
144 # validate names
145 _invalid = []
146 _valid = []
147 for idx in range(len(_list)):
148 _name = _list[idx]
149 if not self.validate_name(_name):
150 _invalid.append(_name)
151 else:
152 _valid.append(_name)
154 return _valid
157utils = Utils()