1
+ #!/usr/bin/env python
2
+
3
+ '''
4
+ Purpose: Update project versions with licenses of their subprojects (components)
5
+
6
+ usage: update_project_with_component_licenses.py [-h] -u BASE_URL -t TOKEN_FILE [-nv]
7
+
8
+ options:
9
+ -h, --help show this help message and exit
10
+ -u BASE_URL, --base-url BASE_URL
11
+ Hub server URL e.g. https://your.blackduck.url
12
+ -t TOKEN_FILE, --token-file TOKEN_FILE
13
+ containing access token
14
+ -nv, --no-verify disable TLS certificate verification
15
+ -p PROJECT_NAME, --project-name PROJECT_NAME
16
+ Project Name
17
+ -pv VERSION_NAME, --version-name VERSION_NAME
18
+ Project Version Name
19
+ '''
20
+
21
+ import argparse
22
+ import json
23
+ import logging
24
+ import sys
25
+ import requests
26
+
27
+ from pprint import pprint
28
+ from blackduck import Client
29
+ from collections import defaultdict
30
+
31
+ def parse_command_args ():
32
+ parser = argparse .ArgumentParser ("update_project_with_component_licenses.py [-h] -u BASE_URL -t TOKEN_FILE [-nv] " )
33
+ parser .add_argument ("-u" , "--base-url" , required = True , help = "Hub server URL e.g. https://your.blackduck.url" )
34
+ parser .add_argument ("-t" , "--token-file" , dest = 'token_file' , required = True , help = "containing access token" )
35
+ parser .add_argument ("-nv" , "--no-verify" , dest = 'no_verify' , action = 'store_false' , help = "disable TLS certificate verification" )
36
+ parser .add_argument ("-p" , "--project_name" , required = True , help = "Provide Project Name here" )
37
+ parser .add_argument ("-v" , "--version_name" ). help = "Provide Project Version here"
38
+ return parser .parse_args ()
39
+
40
+ def main ():
41
+ args = parse_command_args ()
42
+ with open (args .token_file , 'r' ) as tf :
43
+ access_token = tf .readline ().strip ()
44
+ global bd
45
+ bd = Client (base_url = args .base_url , token = access_token , verify = args .no_verify , timeout = 60.0 , retries = 4 )
46
+ process_project_version (args .project_name , args .version_name , args )
47
+
48
+ def process_project_version (project_name , version_name , args ):
49
+ #Validating only 1 Project
50
+ params = {
51
+ 'q' : [f"name:{ args .project_name } " ]
52
+ }
53
+ projects = [p for p in bd .get_resource ('projects' , params = params ) if p ['name' ] == args .project_name ]
54
+ assert len (projects ) == 1 , f"There should be one, and only one project named { args .project_name } . We found { len (projects )} "
55
+ project = projects [0 ]
56
+
57
+ #Validates only 1 Version
58
+ params = {
59
+ 'q' : [f"versionName:{ args .version_name } " ]
60
+ }
61
+ versions = [v for v in bd .get_resource ('versions' , project , params = params ) if v ['versionName' ] == args .version_name ]
62
+ assert len (versions ) == 1 , f"There should be one, and only one version named { args .version_name } . We found { len (versions )} "
63
+ version = versions [0 ]
64
+
65
+
66
+
67
+ #Return only sub-projects, not components
68
+ components = (
69
+ c for c in bd .get_resource ('components' ,version ) if c ['componentType' ] == "SUB_PROJECT"
70
+ )
71
+ for components in components :
72
+ #JSON body
73
+ body = defaultdict (list )
74
+
75
+ existing_licenses = []
76
+
77
+ #Defining subcomponents
78
+ body ["componentName" ]= components ['componentName' ]
79
+ body ["componentVersionName" ]= components ['componentVersionName' ]
80
+ body ["component" ]= components ['component' ]
81
+ body ["componentVersion" ]= components ['componentVersion' ]
82
+ body ["componentType" ]= "SUB_PROJECT"
83
+ pprint (components ['componentName' ])
84
+ pprint (components ['componentVersionName' ])
85
+ url = components ['_meta' ]['href' ]
86
+ #Capture current License statement of components to add to
87
+ if len (components ['licenses' ][0 ]['licenses' ]) > 0 :
88
+ for i , v in enumerate (components ['licenses' ][0 ]['licenses' ]):
89
+ parent_license_display = components ['licenses' ][0 ]['licenses' ][i ]['licenseDisplay' ]
90
+ parent_license = components ['licenses' ][0 ]['licenses' ][i ]['license' ]
91
+ addlicense = {"licenseDisplay" :parent_license_display ,"license" : parent_license }
92
+ body ['licenses' ].append (addlicense )
93
+ if parent_license_display not in existing_licenses :
94
+ existing_licenses .append (parent_license_display )
95
+ else :
96
+ parent_license_display = components ['licenses' ][0 ]['licenses' ][0 ]['licenseDisplay' ]
97
+ parent_license = components ['licenses' ][0 ]['licenses' ][0 ]['license' ]
98
+ addlicense = {"licenseDisplay" :parent_license_display ,"license" : parent_license }
99
+ body ['licenses' ].append (addlicense )
100
+ if parent_license_display not in existing_licenses :
101
+ existing_licenses .append (parent_license_display )
102
+ #Retrieving componentName values
103
+ subprojects = [p for p in bd .get_resource ('projects' ) if p ['name' ] == components ['componentName' ]]
104
+ subproject = subprojects [0 ]
105
+ subversions = [v for v in bd .get_resource ('versions' , subproject ) if v ['versionName' ] == components ['componentVersionName' ]]
106
+ subversion = subversions [0 ]
107
+ for subcomponent in bd .get_resource ('components' ,subversion ):
108
+ #Parse through multiple licenses
109
+ if len (subcomponent ['licenses' ][0 ]['licenses' ]) > 0 :
110
+ for i , v in enumerate (subcomponent ['licenses' ][0 ]['licenses' ]):
111
+ child_license_display = subcomponent ['licenses' ][0 ]['licenses' ][i ]['licenseDisplay' ]
112
+ child_license = subcomponent ['licenses' ][0 ]['licenses' ][i ]['license' ]
113
+ addlicense = {"licenseDisplay" :child_license_display ,"license" : child_license }
114
+ if child_license_display not in existing_licenses :
115
+ body ['licenses' ].append (addlicense )
116
+ existing_licenses .append (child_license_display )
117
+ #When only one license return it
118
+ else :
119
+ child_license_display = subcomponent ['licenses' ][0 ]['licenseDisplay' ]
120
+ child_license = subcomponent ['licenses' ][0 ]['license' ]
121
+ addlicense = {"licenseDisplay" :child_license_display ,"license" : child_license }
122
+ if child_license_display not in existing_licenses :
123
+ body ['licenses' ].append (addlicense )
124
+ existing_licenses .append (child_license_display )
125
+ pprint (dict (body ))
126
+ try :
127
+ r = bd .session .put (url ,json = (dict (body )))
128
+ if r .status_code == 200 :
129
+ print ("updated project" )
130
+ except requests .HTTPError as err :
131
+ bd .http_error_handler (err )
132
+ if __name__ == "__main__" :
133
+ sys .exit (main ())
0 commit comments