blob: a07e51b313cd807fe185c5932426af159f3a30bc [file] [log] [blame]
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +03001
Dennis Dmitriev6bd44252017-06-22 17:33:40 +03002import copy
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +03003import hashlib
4import os
5import re
6import tarfile
7
8import urllib2
9import yaml
10
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +030011
Dennis Dmitriev6bd44252017-06-22 17:33:40 +030012def walkfiles(topdir, verbose=False):
13 walker = os.walk(topdir)
14 opener = open
15 prefix = ''
16 isdir = os.path.isdir(topdir)
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +030017
18 if isdir:
19 for dirName, subdirList, fileList in walker:
20 for filename in fileList:
21 filepath = os.path.join(dirName,filename)
22 if verbose:
23 print (prefix + filepath)
24 with OpenFile(filepath, opener) as log:
25 yield (log)
26 else:
27 if verbose:
28 print (topdir)
29 with OpenFile(topdir, opener) as log:
30 yield (log)
31
32
33def yaml_read(yaml_file):
34 if os.path.isfile(yaml_file):
35 with open(yaml_file, 'r') as f:
36 return yaml.load(f)
37 else:
38 print("\'{}\' is not a file!".format(yaml_file))
39
40
41class OpenFile(object):
42
43 fname = None
44 opener = None
45 readlines = None
46 fobj = None
47
48 def __init__(self, fname, opener):
49 self.fname = fname
50 self.opener = opener
51
52 def get_parser(self):
53 parsers = {'/lastlog': self.fake_parser,
54 '/wtmp': self.fake_parser,
55 '/btmp': self.fake_parser,
56 '/atop.log': self.fake_parser,
57 '/atop_': self.fake_parser,
58 '/atop_current': self.fake_parser,
59 '/supervisord.log': self.docker_parser,
60 '.gz': self.gz_parser,
61 '.bz2': self.gz_parser,
62 }
63 for w in parsers.keys():
64 if w in self.fname:
65 self.readlines = parsers[w]
66 return
67 try:
68 self.fobj = self.opener(self.fname, 'r')
69 self.readlines = self.plaintext_parser
70 except IOError as e:
71 print("Error opening file {0}: {1}".format(self.fname, e))
72 if self.fobj:
73 self.fobj.close()
74 self.fobj = None
75 self.readlines = self.fake_parser
76
77 def plaintext_parser(self):
78 try:
79 for s in self.fobj.readlines():
80 yield s
81 except IOError as e:
82 print("Error reading file {0}: {1}".format(self.fname, e))
83
84 def fake_parser(self):
85 yield ''
86
87 def docker_parser(self):
88 yield ''
89
90 def gz_parser(self):
91 yield ''
92
93 def bz2_parser(self):
94 yield ''
95
96 def __enter__(self):
97 self.get_parser()
98 return self
99
100 def __exit__(self, x, y, z):
101 if self.fobj:
102 self.fobj.close()
103
104
105def get_nested_key(data, path=None):
106 if type(path) is not list:
107 raise("Use 'list' object with key names for 'path'")
108 for key in path:
109 value = data.get(key, None)
110 if value:
111 data = value
112 else:
113 return None
114 return data
115
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300116
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300117def remove_nested_key(data, path=None):
118 if type(path) is not list:
119 raise("Use 'list' object with key names for 'path'")
120
121 # Remove the value from the specified key
122 val = get_nested_key(data, path[:-1])
123 val[path[-1]] = None
124
125 # Clear parent keys if empty
126 while path:
127 val = get_nested_key(data, path)
128 if val:
129 # Non-empty value, nothing to do
130 return
131 else:
132 get_nested_key(data, path[:-1]).pop(path[-1])
133 path = path[:-1]
134
135
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300136def get_all_reclass_params(paths, verbose=False):
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300137 """Return dict with all used values for each param"""
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300138 _params = dict()
139 for path in paths:
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300140 for log in walkfiles(path, verbose):
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300141 if log.fname.endswith('.yml'):
142 model = yaml_read(log.fname)
143 if model is not None:
144 # Collect all params from the models
145 _param = get_nested_key(model, ['parameters', '_param'])
146 if _param:
147 for key, val in _param.items():
148 if key in _params:
Dennis Dmitrievefaa1352017-06-19 12:56:11 +0300149 # Keep list values sorted
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300150 _params[key].append(val)
Dennis Dmitrievefaa1352017-06-19 12:56:11 +0300151 _params[key] = sorted(_params[key])
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300152 else:
153 _params[key] = [val]
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300154 return _params
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300155
156
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300157def remove_reclass_parameter(paths, key,
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300158 verbose=False,
159 pretend=False):
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300160 """Removes specified key from parameters from all reclass models
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300161
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300162 :param key: string with point-separated nested objects, for
163 example: parameters.linux.network.interface
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300164 :rtype dict: { 'file path': {nested_key}, ...}
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300165 """
166 remove_key = key.split('.')
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300167 found_keys = {}
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300168
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300169 for path in paths:
170 for fyml in walkfiles(path, verbose=verbose):
171 if fyml.fname.endswith('.yml'):
172 model = yaml_read(fyml.fname)
173 if model is not None:
Dennis Dmitrieve56c8b92017-06-16 01:53:16 +0300174
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300175 # Clear linux.network.interfaces
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300176 nested_key = get_nested_key(model, remove_key)
177 if nested_key:
178 found_keys[fyml.fname] = copy.deepcopy(nested_key)
179 if pretend:
180 print("\nFound {0} in {1}".format('.'.join(remove_key),
181 fyml.fname))
182 print(yaml.dump(nested_key, default_flow_style=False))
183 else:
184 print("\nRemoving {0} from {1}".format('.'.join(remove_key),
185 fyml.fname))
186 print(yaml.dump(nested_key, default_flow_style=False))
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300187
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300188 remove_nested_key(model, remove_key)
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300189
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300190 with open(fyml.fname, 'w') as f:
191 f.write(
192 yaml.dump(
193 model, default_flow_style=False
194 )
Dennis Dmitriev672bd442017-06-16 18:13:54 +0300195 )
Dennis Dmitriev6bd44252017-06-22 17:33:40 +0300196 return found_keys