Adam Števko
2018-10-19 4041174dc030925a69b05c5caa8dec17a1b9154d
commit | author | age
404117 1 #!/usr/bin/python2.7
2
3 #
4 # This file and its contents are supplied under the terms of the
5 # Common Development and Distribution License ("CDDL"), version 1.0.
6 # You may only use this file in accordance with the terms of version
7 # 1.0 of the CDDL.
8 #
9 # A full copy of the text of the CDDL should have accompanied this
10 # source.  A copy of the CDDL is also available via the Internet at
11 # http://www.illumos.org/license/CDDL.
12 #
13
14 #
15 # Copyright 2018 Adam Stevko
16 #
17
18 #
19 # mapping.py - generate mapping between component FMRI and component package names, to be used for different purposes,
20 # e.g. checking for outdated pacakges, vulnerable packages etc.
21 #
22
23 from __future__ import print_function, absolute_import
24
25 import argparse
26 import json
27 import os
28 import re
29 import logging
30 import subprocess
31 import multiprocessing
32 import sys
33
34 try:
35     from scandir import walk
36 except ImportError:
37     from os import walk
38
39 logger = logging.getLogger('userland-mapping')
40
41 COMONENT_MAPPING_FILENAME = 'mapping.json'
42
43
44 def find_component_paths(path, subdir='components', debug=False):
45     expression = re.compile(r'.+\.p5m$', re.IGNORECASE)
46
47     paths = []
48     workspace_path = os.path.join(path, subdir)
49
50     for dirpath, dirnames, filenames in walk(workspace_path):
51         for name in filenames:
52             if expression.match(name):
53                 paths.append(dirpath)
54                 del dirnames[:]
55                 break
56
57     return paths
58
59
60 def generate_component_data(component_path):
61     result = []
62
63     proc = subprocess.Popen(['gmake', 'print-value-COMPONENT_NAME', 'print-package-names'],
64                             stdout=subprocess.PIPE,
65                             stderr=subprocess.PIPE,
66                             cwd=component_path)
67
68     for out in proc.stdout:
69         result.append(out.rstrip())
70
71     component_name = result[0]
72     component_fmris = result[1:]
73     component_relative_path = component_path.split(os.environ['WS_TOP'])[-1].replace('/', '', 1)
74
75     return component_fmris, component_name, component_relative_path
76
77
78 def generate_userland_mapping(workspace_path, subdir='components'):
79     mapping = []
80
81     paths = find_component_paths(path=workspace_path, subdir=subdir)
82     pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())
83     results = pool.map(generate_component_data, paths)
84
85     for component_fmris, component_name, component_relative_path in results:
86         for component_fmri in component_fmris:
87             mapping.append({'component_name': component_name,
88                             'component_fmri': component_fmri,
89                             'component_path': component_relative_path})
90
91     component_mapping_file = os.path.join(workspace_path, subdir, COMONENT_MAPPING_FILENAME)
92     with open(component_mapping_file, 'w') as f:
93         f.write(json.dumps(mapping, sort_keys=True, indent=4))
94
95
96 def main():
97     parser = argparse.ArgumentParser()
98
99     parser.add_argument('-w', '--workspace', default=os.getenv('WS_TOP'), help='Path to workspace')
100     parser.add_argument('--subdir', default='components', help='Directory holding components')
101
102     args = parser.parse_args()
103
104     workspace = args.workspace
105     subdir = args.subdir
106
107     generate_userland_mapping(workspace_path=workspace, subdir=subdir)
108
109
110 if __name__ == '__main__':
111     main()