Aurelien Larcher
2020-06-01 1e2fed24f6ea2260055ff4be5afe5f8d3709a054
commit | author | age
fb10ba 1 #!/usr/bin/python3.5
404117 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 import argparse
24 import json
25 import os
26 import re
27 import logging
28 import subprocess
29 import multiprocessing
30
1e2fed 31 from bass.component import BassComponent
AL 32
404117 33 try:
34     from scandir import walk
35 except ImportError:
36     from os import walk
37
38 logger = logging.getLogger('userland-mapping')
39
1e2fed 40 COMPONENT_MAPPING_FILENAME = 'mapping.json'
404117 41
42
43 def find_component_paths(path, subdir='components', debug=False):
44     expression = re.compile(r'.+\.p5m$', re.IGNORECASE)
45
46     paths = []
47     workspace_path = os.path.join(path, subdir)
48
49     for dirpath, dirnames, filenames in walk(workspace_path):
50         for name in filenames:
51             if expression.match(name):
52                 paths.append(dirpath)
53                 del dirnames[:]
54                 break
55
56     return paths
57
58
11232f 59 def generate_component_data(component_path, subdir='components'):
404117 60     result = []
1e2fed 61     component = BassComponent(path=component_path)
AL 62     component_name = component.component_name
63     if not component_name:
64         raise ValueError('Component name is empty for path ' + component_path + '.')
65     component_fmris = component.supplied_packages
66     if not component_fmris:
67         raise ValueError('Component FMRIs is empty for path ' + component_path + '.')
404117 68
11232f 69     component_relative_path = component_path.split(os.path.join(os.environ['WS_TOP'], subdir))[-1].replace('/', '', 1)
404117 70
71     return component_fmris, component_name, component_relative_path
72
73
74 def generate_userland_mapping(workspace_path, subdir='components'):
75     mapping = []
76
77     paths = find_component_paths(path=workspace_path, subdir=subdir)
78     pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())
79     results = pool.map(generate_component_data, paths)
80
81     for component_fmris, component_name, component_relative_path in results:
82         for component_fmri in component_fmris:
1e2fed 83             mapping.append({'name': component_name,
AL 84                             'fmri': component_fmri,
85                             'path': component_relative_path})
404117 86
1e2fed 87     component_mapping_file = os.path.join(workspace_path, subdir, COMPONENT_MAPPING_FILENAME)
404117 88     with open(component_mapping_file, 'w') as f:
89         f.write(json.dumps(mapping, sort_keys=True, indent=4))
90
91
92 def main():
93     parser = argparse.ArgumentParser()
94
95     parser.add_argument('-w', '--workspace', default=os.getenv('WS_TOP'), help='Path to workspace')
96     parser.add_argument('--subdir', default='components', help='Directory holding components')
97
98     args = parser.parse_args()
99
100     workspace = args.workspace
101     subdir = args.subdir
102
103     generate_userland_mapping(workspace_path=workspace, subdir=subdir)
104
105 if __name__ == '__main__':
106     main()