Total Complexity | 52 |
Total Lines | 342 |
Duplicated Lines | 53.51 % |
Coverage | 0% |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like utils.rule_dir_diff often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | #!/usr/bin/env python |
||
2 | |||
3 | from __future__ import print_function |
||
4 | |||
5 | import argparse |
||
6 | import os |
||
7 | import sys |
||
8 | |||
9 | import json |
||
10 | import pprint |
||
11 | |||
12 | import ssg.build_yaml |
||
13 | import ssg.oval |
||
14 | import ssg.build_remediations |
||
15 | import ssg.rule_dir_stats as rds |
||
16 | import ssg.rules |
||
17 | import ssg.yaml |
||
18 | |||
19 | |||
20 | SSG_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) |
||
21 | |||
22 | |||
23 | def parse_args(): |
||
24 | parser = argparse.ArgumentParser() |
||
25 | parser.add_argument("--left", type=str, action="store", default="build/old_rule_dirs.json", |
||
26 | help="File to read json output of rule_dir_json from (defaults to " + |
||
27 | "build/old_rule_dirs.json); left such file for diffing") |
||
28 | parser.add_argument("--right", type=str, action="store", default="build/rule_dirs.json", |
||
29 | help="File to read json output of rule_dir_json from (defaults to " + |
||
30 | "build/rule_dirs.json); right such file for diffing") |
||
31 | |||
32 | parser.add_argument("-p", "--products", type=str, action="store", default="all", |
||
33 | help="Products to inquire about, as a comma separated list") |
||
34 | parser.add_argument("-t", "--strict", action="store_true", |
||
35 | help="Enforce strict --products checking against rule.yml prodtype only") |
||
36 | parser.add_argument("-q", "--query", type=str, action="store", default=None, |
||
37 | help="Limit actions to only act on a comma separated list of rule_ids") |
||
38 | |||
39 | parser.add_argument("-m", "--missing", action="store_true", |
||
40 | help="List rules which are missing OVALs or fixes") |
||
41 | parser.add_argument("-2", "--two-plus", action="store_true", |
||
42 | help="List rules which have two or more OVALs or fixes") |
||
43 | parser.add_argument("-r", "--prodtypes", action="store_true", |
||
44 | help="List rules which have different YAML prodtypes from checks+fix prodtypes") |
||
45 | parser.add_argument("-n", "--product-names", action="store_true", |
||
46 | help="List rules which have product specific objects with broader accepted products") |
||
47 | |||
48 | parser.add_argument("-o", "--ovals-only", action="store_true", |
||
49 | help="Only output information about OVALs") |
||
50 | parser.add_argument("-f", "--fixes-only", action="store_true", |
||
51 | help="Only output information about fixes") |
||
52 | |||
53 | parser.add_argument("--left-only", action="store_true", |
||
54 | help="Print only information from the left that is " + |
||
55 | "not in the right") |
||
56 | parser.add_argument("--right-only", action="store_true", |
||
57 | help="Print only information from the right that is " + |
||
58 | "not in the left") |
||
59 | parser.add_argument("--show-common", action="store_true", |
||
60 | help="Also print information that is common to both") |
||
61 | |||
62 | parser.add_argument("-s", "--summary-only", action="store_true", |
||
63 | help="Only output summary information") |
||
64 | |||
65 | return parser.parse_args() |
||
66 | |||
67 | |||
68 | def prefixed_print(statement, prefix): |
||
69 | print("%s %s" % (prefix, statement)) |
||
70 | |||
71 | |||
72 | def print_specifics(args, headline, data, prefix): |
||
73 | if not args.summary_only and data: |
||
74 | prefixed_print(headline, prefix) |
||
75 | for line in data: |
||
76 | prefixed_print(line, prefix) |
||
77 | print("\n") |
||
78 | |||
79 | |||
80 | def print_summary(args, statements, data, prefix): |
||
81 | affected_rules, affected_ovals, affected_remediations, affected_remediations_type = data |
||
82 | |||
83 | prefixed_print(statements[0], prefix) |
||
84 | prefixed_print(statements[1] % affected_rules, prefix) |
||
85 | if not args.fixes_only: |
||
86 | prefixed_print(statements[2] % (affected_ovals, affected_rules), prefix) |
||
87 | if not args.ovals_only: |
||
88 | prefixed_print(statements[3] % (affected_remediations, affected_rules), prefix) |
||
89 | for r_type in ssg.build_remediations.REMEDIATION_TO_EXT_MAP: |
||
90 | r_missing = affected_remediations_type[r_type] |
||
91 | prefixed_print(statements[4] % (r_type, r_missing, affected_rules), prefix) |
||
92 | print("\n") |
||
93 | |||
94 | |||
95 | def select_indices(data, indices): |
||
96 | return [data[index] for index in indices] |
||
97 | |||
98 | |||
99 | View Code Duplication | def process_diff_missing(args, left_rules, right_rules): |
|
|
|||
100 | data = rds.walk_rules_diff(args, left_rules, right_rules, rds.missing_oval, rds.missing_remediation) |
||
101 | result = rds.walk_rules_diff_stats(data) |
||
102 | left_only_data, right_only_data, left_changed_data, right_changed_data, common_data = result |
||
103 | |||
104 | statements = ["Missing Objects Summary", |
||
105 | "Total affected rules: %d", |
||
106 | "Rules with no OVALs: %d / %d", |
||
107 | "Rules without any remediations: %d / %d", |
||
108 | "Rules with no %s remediations: %d / %d"] |
||
109 | |||
110 | if not args.right_only: |
||
111 | print_specifics(args, "Missing Objects Specifics - Left Only:", left_only_data[5], '<') |
||
112 | print_specifics(args, "Missing Objects Specifics - Left Changed:", left_changed_data[5], '<') |
||
113 | |||
114 | if args.show_common: |
||
115 | print_specifics(args, "Missing Objects Specifics - Common:", common_data[5], '=') |
||
116 | |||
117 | if not args.left_only: |
||
118 | print_specifics(args, "Missing Objects Specifics - Right Changed:", right_changed_data[5], '>') |
||
119 | print_specifics(args, "Missing Objects Specifics - Right Only:", right_only_data[5], '>') |
||
120 | |||
121 | data_indices = [0, 1, 3, 4] |
||
122 | |||
123 | if not args.right_only: |
||
124 | statements[0] = "Missing Objects Summary - Left Only:" |
||
125 | l_d = select_indices(left_only_data, data_indices) |
||
126 | print_summary(args, statements, l_d, '<') |
||
127 | |||
128 | statements[0] = "Missing Objects Summary - Left Changed:" |
||
129 | l_d = select_indices(left_changed_data, data_indices) |
||
130 | print_summary(args, statements, l_d, '<') |
||
131 | |||
132 | if args.show_common: |
||
133 | statements[0] = "Missing Objects Summary - Common:" |
||
134 | c_d = select_indices(common_data, data_indices) |
||
135 | print_summary(args, statements, c_d, '=') |
||
136 | |||
137 | if not args.left_only: |
||
138 | statements[0] = "Missing Objects Summary - Right Changed:" |
||
139 | r_d = select_indices(right_changed_data, data_indices) |
||
140 | print_summary(args, statements, r_d, '>') |
||
141 | |||
142 | statements[0] = "Missing Objects Summary - Right Only:" |
||
143 | r_d = select_indices(right_only_data, data_indices) |
||
144 | print_summary(args, statements, r_d, '>') |
||
145 | |||
146 | |||
147 | View Code Duplication | def process_diff_two_plus(args, left_rules, right_rules): |
|
148 | data = rds.walk_rules_diff(args, left_rules, right_rules, rds.two_plus_oval, rds.two_plus_remediation) |
||
149 | result = rds.walk_rules_diff_stats(data) |
||
150 | left_only_data, right_only_data, left_changed_data, right_changed_data, common_data = result |
||
151 | |||
152 | statements = ["Two Plus Objects Summary:", |
||
153 | "Total affected rules: %d", |
||
154 | "Rules with two or more OVALs: %d / %d", |
||
155 | "Rules with two or more remediations: %d / %d", |
||
156 | "Rules with two or more %s remediations: %d / %d"] |
||
157 | |||
158 | if not args.right_only: |
||
159 | print_specifics(args, "Two Plus Objects Specifics - Left Only:", left_only_data[5], '<') |
||
160 | print_specifics(args, "Two Plus Objects Specifics - Left Changed:", left_changed_data[5], '<') |
||
161 | |||
162 | if args.show_common: |
||
163 | print_specifics(args, "Two Plus Objects Specifics - Common:", common_data[5], '=') |
||
164 | |||
165 | if not args.left_only: |
||
166 | print_specifics(args, "Two Plus Objects Specifics - Right Changed:", right_changed_data[5], '>') |
||
167 | print_specifics(args, "Two Plus Objects Specifics - Right Only:", right_only_data[5], '>') |
||
168 | |||
169 | data_indices = [0, 1, 2, 4] |
||
170 | |||
171 | if not args.right_only: |
||
172 | statements[0] = "Two Plus Objects Summary - Left Only:" |
||
173 | l_d = select_indices(left_only_data, data_indices) |
||
174 | print_summary(args, statements, l_d, '<') |
||
175 | |||
176 | statements[0] = "Two Plus Objects Summary - Left Changed:" |
||
177 | l_d = select_indices(left_changed_data, data_indices) |
||
178 | print_summary(args, statements, l_d, '<') |
||
179 | |||
180 | if args.show_common: |
||
181 | statements[0] = "Two Plus Objects Summary - Common:" |
||
182 | c_d = select_indices(common_data, data_indices) |
||
183 | print_summary(args, statements, c_d, '=') |
||
184 | |||
185 | if not args.left_only: |
||
186 | statements[0] = "Two Plus Objects Summary - Right Changed:" |
||
187 | r_d = select_indices(right_changed_data, data_indices) |
||
188 | print_summary(args, statements, r_d, '>') |
||
189 | |||
190 | statements[0] = "Two Plus Objects Summary - Right Only:" |
||
191 | r_d = select_indices(right_only_data, data_indices) |
||
192 | print_summary(args, statements, r_d, '>') |
||
193 | |||
194 | |||
195 | View Code Duplication | def process_diff_prodtypes(args, left_rules, right_rules): |
|
196 | data = rds.walk_rules_diff(args, left_rules, right_rules, rds.prodtypes_oval, rds.prodtypes_remediation) |
||
197 | result = rds.walk_rules_diff_stats(data) |
||
198 | left_only_data, right_only_data, left_changed_data, right_changed_data, common_data = result |
||
199 | |||
200 | statements = ["Prodtypes Objects Summary", |
||
201 | "Total affected rules: %d", |
||
202 | "Rules with differing prodtypes between YAML and OVALs: %d / %d", |
||
203 | "Rules with differing prodtypes between YAML and remediations: %d / %d", |
||
204 | "Rules with differing prodtypes between YAML and %s remediations: %d / %d"] |
||
205 | |||
206 | if not args.right_only: |
||
207 | print_specifics(args, "Prodtypes Objects Specifics - Left Only:", left_only_data[5], '<') |
||
208 | print_specifics(args, "Prodtypes Objects Specifics - Left Changed:", left_changed_data[5], '<') |
||
209 | |||
210 | if args.show_common: |
||
211 | print_specifics(args, "Prodtypes Objects Specifics - Common:", common_data[5], '=') |
||
212 | |||
213 | if not args.left_only: |
||
214 | print_specifics(args, "Prodtypes Objects Specifics - Right Changed:", right_changed_data[5], '>') |
||
215 | print_specifics(args, "Prodtypes Objects Specifics - Right Only:", right_only_data[5], '>') |
||
216 | |||
217 | data_indices = [0, 1, 2, 4] |
||
218 | |||
219 | if not args.right_only: |
||
220 | statements[0] = "Prodtypes Objects Summary - Left Only:" |
||
221 | l_d = select_indices(left_only_data, data_indices) |
||
222 | print_summary(args, statements, l_d, '<') |
||
223 | |||
224 | statements[0] = "Prodtypes Objects Summary - Left Changed:" |
||
225 | l_d = select_indices(left_changed_data, data_indices) |
||
226 | print_summary(args, statements, l_d, '<') |
||
227 | |||
228 | if args.show_common: |
||
229 | statements[0] = "Prodtypes Objects Summary - Common:" |
||
230 | c_d = select_indices(common_data, data_indices) |
||
231 | print_summary(args, statements, c_d, '=') |
||
232 | |||
233 | if not args.left_only: |
||
234 | statements[0] = "Prodtypes Objects Summary - Right Changed:" |
||
235 | r_d = select_indices(right_changed_data, data_indices) |
||
236 | print_summary(args, statements, r_d, '>') |
||
237 | |||
238 | statements[0] = "Prodtypes Objects Summary - Right Only:" |
||
239 | r_d = select_indices(right_only_data, data_indices) |
||
240 | print_summary(args, statements, r_d, '>') |
||
241 | |||
242 | |||
243 | View Code Duplication | def process_diff_product_names(args, left_rules, right_rules): |
|
244 | data = rds.walk_rules_diff(args, left_rules, right_rules, rds.product_names_oval, rds.product_names_remediation) |
||
245 | result = rds.walk_rules_diff_stats(data) |
||
246 | left_only_data, right_only_data, left_changed_data, right_changed_data, common_data = result |
||
247 | |||
248 | if not args.right_only: |
||
249 | print_specifics(args, "Product Names Objects Specifics - Left Only:", left_only_data[5], '<') |
||
250 | print_specifics(args, "Product Names Objects Specifics - Left Changed:", left_changed_data[5], '<') |
||
251 | |||
252 | if args.show_common: |
||
253 | print_specifics(args, "Product Names Objects Specifics - Common:", common_data[5], '=') |
||
254 | |||
255 | if not args.left_only: |
||
256 | print_specifics(args, "Product Names Objects Specifics - Right Changed:", right_changed_data[5], '>') |
||
257 | print_specifics(args, "Product Names Objects Specifics - Right Only:", right_only_data[5], '>') |
||
258 | |||
259 | data_indices = [0, 1, 2, 4] |
||
260 | statements = ["Product Names Objects Summary:", |
||
261 | "Total affected rules: %d", |
||
262 | "Rules with differing products and OVAL names: %d / %d", |
||
263 | "Rules with differing product and remediation names: %d / %d", |
||
264 | "Rules with differing product and %s remediation names: %d / %d"] |
||
265 | |||
266 | if not args.right_only: |
||
267 | statements[0] = "Product Names Objects Summary - Left Only:" |
||
268 | l_d = select_indices(left_only_data, data_indices) |
||
269 | print_summary(args, statements, l_d, '<') |
||
270 | |||
271 | statements[0] = "Product Names Objects Summary - Left Changed:" |
||
272 | l_d = select_indices(left_changed_data, data_indices) |
||
273 | print_summary(args, statements, l_d, '<') |
||
274 | |||
275 | if args.show_common: |
||
276 | statements[0] = "Product Names Objects Summary - Common:" |
||
277 | c_d = select_indices(common_data, data_indices) |
||
278 | print_summary(args, statements, c_d, '=') |
||
279 | |||
280 | if not args.left_only: |
||
281 | statements[0] = "Product Names Objects Summary - Right Changed:" |
||
282 | r_d = select_indices(right_changed_data, data_indices) |
||
283 | print_summary(args, statements, r_d, '>') |
||
284 | |||
285 | statements[0] = "Product Names Objects Summary - Right Only:" |
||
286 | r_d = select_indices(right_only_data, data_indices) |
||
287 | print_summary(args, statements, r_d, '>') |
||
288 | |||
289 | |||
290 | def main(): |
||
291 | args = parse_args() |
||
292 | |||
293 | linux_products, other_products = ssg.products.get_all(SSG_ROOT) |
||
294 | all_products = linux_products.union(other_products) |
||
295 | |||
296 | left_file = open(args.left, 'r') |
||
297 | left_rules = json.load(left_file) |
||
298 | |||
299 | right_file = open(args.right, 'r') |
||
300 | right_rules = json.load(right_file) |
||
301 | |||
302 | if left_rules == right_rules: |
||
303 | print("No difference. Please use rule_dir_stats to inspect one of these files.") |
||
304 | sys.exit(0) |
||
305 | |||
306 | if args.products.lower() == 'all': |
||
307 | args.products = all_products |
||
308 | elif args.products.lower() == 'linux': |
||
309 | args.products = linux_products |
||
310 | elif args.products.lower() == 'other': |
||
311 | args.products = other_products |
||
312 | else: |
||
313 | args.products = args.products.split(',') |
||
314 | args.products = set(args.products) |
||
315 | |||
316 | left_query_keys = rds.filter_rule_ids(set(left_rules), args.query) |
||
317 | right_query_keys = rds.filter_rule_ids(set(right_rules), args.query) |
||
318 | args.query = left_query_keys.union(right_query_keys) |
||
319 | print("Total number of queried rules: %d\n" % len(args.query)) |
||
320 | |||
321 | if not args.missing and not args.two_plus and not args.prodtypes and not args.product_names: |
||
322 | args.missing = True |
||
323 | args.two_plus = True |
||
324 | args.prodtypes = True |
||
325 | |||
326 | print("< Total number of known rule directories: %d" % len(left_rules)) |
||
327 | print("> Total number of known rule directories: %d\n" % len(right_rules)) |
||
328 | print("= Total number of queried rules: %d\n" % len(args.query)) |
||
329 | |||
330 | if args.missing: |
||
331 | process_diff_missing(args, left_rules, right_rules) |
||
332 | if args.two_plus: |
||
333 | process_diff_two_plus(args, left_rules, right_rules) |
||
334 | if args.prodtypes: |
||
335 | process_diff_prodtypes(args, left_rules, right_rules) |
||
336 | if args.product_names: |
||
337 | process_diff_product_names(args, left_rules, right_rules) |
||
338 | |||
339 | |||
340 | if __name__ == "__main__": |
||
341 | main() |
||
342 |