Implements use of yaml.safe_load as per sec audit
[releng.git] / utils / opnfv-artifacts.py
1 #!/usr/bin/python
2 # SPDX-license-identifier: Apache-2.0
3 ##############################################################################
4 # Copyright (c) 2016 The Linux Foundation and others
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #  http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16 ##############################################################################
17
18 """
19 Generate JSON listing of OPNFV Artifacts
20
21 This produces a slimmed down version of metadata provided by Google
22 Storage for each artifact. Also excludes a large number of uninteresting
23 files.
24 """
25
26 from apiclient import discovery
27 from apiclient.errors import HttpError
28
29 import argparse
30 import json
31 import os
32 import sys
33
34 api = {
35   'projects': {},
36   'docs': {},
37   'releases': {},
38 }
39
40 releases = [
41   'arno.2015.1.0',
42   'arno.2015.2.0',
43   'brahmaputra.1.0',
44 ]
45
46 # List of file extensions to filter out
47 ignore_extensions = [
48   '.buildinfo',
49   '.woff',
50   '.ttf',
51   '.svg',
52   '.eot',
53   '.pickle',
54   '.doctree',
55   '.js',
56   '.png',
57   '.css',
58   '.gif',
59   '.jpeg',
60   '.jpg',
61   '.bmp',
62 ]
63
64
65 parser = argparse.ArgumentParser(
66              description='OPNFV Artifacts JSON Generator')
67
68 parser.add_argument(
69         '-k',
70         dest='key',
71         default='',
72         help='API Key for Google Cloud Storage')
73
74 parser.add_argument(
75         '-p',
76         default=None,
77         dest='pretty',
78         action='store_const',
79         const=2,
80         help='pretty print the output')
81
82 # Parse and assign arguments
83 args = parser.parse_args()
84 key = args.key
85 pretty_print = args.pretty
86
87
88 def output(item, indent=2):
89     print(json.dumps(item, sort_keys=True, indent=indent))
90
91
92 def has_gerrit_review(dir_list):
93     """
94     If a directory contains an integer, it is assumed to be a gerrit
95     review number
96     """
97     for d in dir_list:
98         if d.isdigit():
99             return int(d)
100     return False
101
102
103 def has_release(dir_list):
104     """
105     Checks if any directory contains a release name
106     """
107     for d in dir_list:
108         if d in releases:
109             return d
110     return False
111
112
113 def has_documentation(dir_list):
114     """
115     Checks for a directory specifically named 'docs'
116     """
117     for d in dir_list:
118         if d == 'docs':
119             return True
120     return False
121
122
123 # Rename this or modify how gerrit review are handled
124 def has_logs(gerrit_review):
125     """
126     If a gerrit review exists, create a link to the review
127     """
128     if gerrit_review:
129         return "https://gerrit.opnfv.org/gerrit/#/c/%s" % gerrit_review
130     return False
131
132
133
134 def has_ignorable_extension(filename):
135     for extension in ignore_extensions:
136         if filename.lower().endswith(extension):
137             return True
138     return False
139
140
141 def get_results(key):
142     """
143     Pull down all metadata from artifacts.opnfv.org
144     and store it in projects as:
145     { 'PROJECT': [file ...], }
146     """
147     storage = discovery.build('storage', 'v1', developerKey=key)
148     files = storage.objects().list(bucket='artifacts.opnfv.org',
149                                    fields='nextPageToken,'
150                                           'items('
151                                               'name,'
152                                               'mediaLink,'
153                                               'updated,'
154                                               'contentType,'
155                                               'size'
156                                           ')')
157     while (files is not None):
158         sites = files.execute()
159
160         for site in sites['items']:
161             # Filter out unneeded files (js, images, css, buildinfo, etc)
162             if has_ignorable_extension(site['name']):
163                 continue
164
165             # Split /foo/bar/ into ['foo', 'bar'] and remove any extra
166             # slashes (ex. /foo//bar/)
167             site_split = filter(None, site['name'].split('/'))
168
169             # Don't do anything if we aren't given files multiple
170             # directories deep
171             if len(site_split) < 2:
172                 continue
173
174             project = site_split[0]
175             name = '/'.join(site_split[1:])
176             proxy = "http://build.opnfv.org/artifacts.opnfv.org/%s" % site['name']
177             if name.endswith('.html'):
178                 href = "http://artifacts.opnfv.org/%s" % site['name']
179                 href_type = 'view'
180             else:
181                 href = site['mediaLink']
182                 href_type = 'download'
183
184             gerrit = has_gerrit_review(site_split)
185             logs = False  # has_logs(gerrit)
186             documentation = has_documentation(site_split)
187             release = has_release(site_split)
188
189             category = 'project'
190             if gerrit:
191                 category = 'gerrit'
192             elif release:
193                 category = 'release'
194             elif logs:
195                 category = 'logs'
196
197             metadata = {
198                 'category': category,
199                 'gerritreview': gerrit,
200                 'release': release,
201                 'name': name,
202                 'size': site['size'],
203                 'time': site['updated'],
204                 'contentType': site['contentType'],
205                 'href': href,
206                 'href_type': href_type,
207                 'proxy_href': proxy,
208             }
209
210             if project in releases:
211                 if project not in api['releases']:
212                     api['releases'][project] = [metadata]
213                 else:
214                     api['releases'][project].append(metadata)
215             else:
216                 if project not in api['projects']:
217                     api['projects'][project] = [metadata]
218                 else:
219                     api['projects'][project].append(metadata)
220
221         files = storage.objects().list_next(files, sites)
222
223     return api
224
225
226 # Fail if there is an invalid response from GCE
227 try:
228     js = get_results(key)
229 except HttpError as e:
230     print >> sys.stderr, e
231     exit(1)
232
233 output(js, indent=pretty_print)