3636from sonar import platform , rules , qualityprofiles , qualitygates , users , groups
3737from sonar import projects , portfolios , applications
3838
39- WRITE_FILE = None
40-
41- _EVERYTHING = [
42- options .WHAT_SETTINGS ,
43- options .WHAT_USERS ,
44- options .WHAT_GROUPS ,
45- options .WHAT_GATES ,
46- options .WHAT_RULES ,
47- options .WHAT_PROFILES ,
48- options .WHAT_PROJECTS ,
49- options .WHAT_APPS ,
50- options .WHAT_PORTFOLIOS ,
51- ]
52-
5339TOOL_NAME = "sonar-config"
5440
41+ DONT_INLINE_LISTS = "dontInlineLists"
42+ FULL_EXPORT = "fullExport"
43+
5544__JSON_KEY_PLATFORM = "platform"
5645__JSON_KEY_SETTINGS = "globalSettings"
5746__JSON_KEY_USERS = "users"
6352__JSON_KEY_APPS = "applications"
6453__JSON_KEY_PORTFOLIOS = "portfolios"
6554
66- __MAP = {
67- options .WHAT_SETTINGS : __JSON_KEY_SETTINGS ,
68- options .WHAT_USERS : __JSON_KEY_USERS ,
69- options .WHAT_GROUPS : __JSON_KEY_GROUPS ,
70- options .WHAT_GATES : __JSON_KEY_GATES ,
71- options .WHAT_RULES : __JSON_KEY_RULES ,
72- options .WHAT_PROFILES : __JSON_KEY_PROFILES ,
73- options .WHAT_PROJECTS : __JSON_KEY_PROJECTS ,
74- options .WHAT_APPS : __JSON_KEY_APPS ,
75- options .WHAT_PORTFOLIOS : __JSON_KEY_PORTFOLIOS ,
76- }
77-
78-
7955_EXPORT_CALLS = {
80- "platform" : [__JSON_KEY_PLATFORM , platform .basics ],
56+ __JSON_KEY_PLATFORM : [__JSON_KEY_PLATFORM , platform .basics ],
8157 options .WHAT_SETTINGS : [__JSON_KEY_SETTINGS , platform .export ],
8258 options .WHAT_RULES : [__JSON_KEY_RULES , rules .export ],
8359 options .WHAT_PROFILES : [__JSON_KEY_PROFILES , qualityprofiles .export ],
8965 options .WHAT_GROUPS : [__JSON_KEY_GROUPS , groups .export ],
9066}
9167
68+ _EVERYTHING = list (_EXPORT_CALLS .keys ())[1 :]
69+
9270
93- def __parse_args (desc ):
71+ def __parse_args (desc : str ) -> object :
72+ """Sets and parses all sonar-config options"""
9473 parser = options .set_common_args (desc )
9574 parser = options .set_key_arg (parser )
9675 parser = options .set_output_file_args (parser , allowed_formats = ("json" , "yaml" ))
9776 parser = options .add_thread_arg (parser , "project export" )
9877 parser = options .set_what (parser , what_list = _EVERYTHING , operation = "export or import" )
9978 parser = options .add_import_export_arg (parser , "configuration" )
10079 parser .add_argument (
101- "--fullExport " ,
80+ f "--{ FULL_EXPORT } " ,
10281 required = False ,
10382 default = False ,
10483 action = "store_true" ,
@@ -115,7 +94,7 @@ def __parse_args(desc):
11594 "and the setting will not be imported at import time" ,
11695 )
11796 parser .add_argument (
118- "--dontInlineLists " ,
97+ f "--{ DONT_INLINE_LISTS } " ,
11998 required = False ,
12099 default = False ,
121100 action = "store_true" ,
@@ -157,96 +136,55 @@ def __convert_for_yaml(json_export: dict[str, any]) -> dict[str, any]:
157136 return json_export
158137
159138
160- def __export_config_sync (endpoint : platform .Platform , what : list [str ], ** kwargs ) -> None :
161- """Exports config in a synchronous way"""
162- export_settings = {
163- "INLINE_LISTS" : not kwargs ["dontInlineLists" ],
164- "EXPORT_DEFAULTS" : kwargs ["exportDefaults" ],
165- "FULL_EXPORT" : kwargs ["fullExport" ],
166- "THREADS" : kwargs [options .NBR_THREADS ],
167- options .REPORT_FILE : kwargs [options .REPORT_FILE ],
168- }
169- if "projects" in what and kwargs [options .KEYS ]:
170- non_existing_projects = [key for key in kwargs [options .KEYS ] if not projects .exists (key , endpoint )]
171- if len (non_existing_projects ) > 0 :
172- utilities .exit_fatal (f"Project key(s) '{ ',' .join (non_existing_projects )} ' do(es) not exist" , errcodes .NO_SUCH_KEY )
173- log .info ("Exporting configuration synchronously from %s" , kwargs [options .URL ])
174- key_list = kwargs [options .KEYS ]
175- what .append ("platform" )
176- sq_settings = {}
177- for what_item , call_data in _EXPORT_CALLS .items ():
178- if what_item not in what :
179- continue
180- ndx , func = call_data
181- try :
182- sq_settings [ndx ] = func (endpoint , export_settings = export_settings , key_list = key_list )
183- except exceptions .UnsupportedOperation as e :
184- log .warning (e .message )
185- except exceptions .ObjectNotFound as e :
186- log .error (e .message )
187- sq_settings = __prep_json_for_write (sq_settings , export_settings )
188- __write_export (sq_settings , kwargs [options .REPORT_FILE ], kwargs [options .FORMAT ])
189- log .info ("Synchronous export of configuration from %s completed" , kwargs ["url" ])
190-
191-
192- def __prep_json_for_write (json_data : types .ObjectJsonRepr , export_settings : types .ConfigSettings ) -> types .ObjectJsonRepr :
193- """Cleans up the JSON before writing"""
194- json_data = utilities .sort_lists (json_data )
195- if not export_settings .get ("FULL_EXPORT" , False ):
196- json_data = utilities .remove_empties (utilities .remove_nones (json_data ))
197- if export_settings .get ("INLINE_LISTS" , True ):
198- json_data = utilities .inline_lists (json_data , exceptions = ("conditions" ,))
199- return json_data
200-
201-
202139def write_objects (queue : Queue [types .ObjectJsonRepr ], fd : TextIO , object_type : str , export_settings : types .ConfigSettings ) -> None :
203140 """
204141 Thread to write projects in the JSON file
205142 """
143+ done = False
206144 prefix = ""
207145 log .info ("Waiting %s to write..." , object_type )
208146 print (f'"{ object_type } ": ' + "{" , file = fd )
209- while True :
147+ while not done :
210148 obj_json = queue .get ()
211- if obj_json is None :
212- queue .task_done ()
213- break
214- obj_json = __prep_json_for_write (obj_json , export_settings )
215- if object_type in ("projects" , "applications" , "portfolios" , "users" ):
216- if object_type == "users" :
217- key = obj_json .pop ("login" , None )
149+ done = obj_json is None
150+ if not done :
151+ obj_json = __prep_json_for_write (obj_json , export_settings )
152+ if object_type in ("projects" , "applications" , "portfolios" , "users" ):
153+ if object_type == "users" :
154+ key = obj_json .pop ("login" , None )
155+ else :
156+ key = obj_json .pop ("key" , None )
157+ log .debug ("Writing %s key '%s'" , object_type [:- 1 ], key )
158+ print (f'{ prefix } "{ key } ": { utilities .json_dump (obj_json )} ' , end = "" , file = fd )
218159 else :
219- key = obj_json .pop ("key" , None )
220- log .debug ("Writing %s key '%s'" , object_type [:- 1 ], key )
221- print (f'{ prefix } "{ key } ": { utilities .json_dump (obj_json )} ' , end = "" , file = fd )
222- else :
223- log .debug ("Writing %s" , object_type )
224- print (f"{ prefix } { utilities .json_dump (obj_json )[2 :- 1 ]} " , end = "" , file = fd )
225- prefix = ",\n "
160+ log .debug ("Writing %s" , object_type )
161+ print (f"{ prefix } { utilities .json_dump (obj_json )[2 :- 1 ]} " , end = "" , file = fd )
162+ prefix = ",\n "
226163 queue .task_done ()
227164 print ("\n }" , file = fd , end = "" )
228165 log .info ("Writing %s complete" , object_type )
229166
230167
231- def __export_config_async (endpoint : platform .Platform , what : list [str ], ** kwargs ) -> None :
168+ def export_config (endpoint : platform .Platform , what : list [str ], ** kwargs ) -> None :
232169 """Exports a platform configuration in a JSON file"""
233170 file = kwargs [options .REPORT_FILE ]
171+ mode = kwargs .get ("mode" , "CONFIG" )
234172 export_settings = {
235- "INLINE_LISTS" : not kwargs [ "dontInlineLists" ] ,
236- "EXPORT_DEFAULTS" : kwargs [ "exportDefaults" ] ,
237- "FULL_EXPORT" : kwargs [ "fullExport" ] ,
238- "MODE" : "CONFIG" ,
173+ "INLINE_LISTS" : False if mode == "MIGRATION" else not kwargs . get ( DONT_INLINE_LISTS , False ) ,
174+ "EXPORT_DEFAULTS" : True ,
175+ "FULL_EXPORT" : False if mode == "MIGRATION" else kwargs . get ( FULL_EXPORT , False ) ,
176+ "MODE" : mode ,
239177 "THREADS" : kwargs [options .NBR_THREADS ],
240- "SKIP_ISSUES" : True ,
178+ "SKIP_ISSUES" : kwargs . get ( "skipIssues" , False ) ,
241179 }
242180 if "projects" in what and kwargs [options .KEYS ]:
243181 non_existing_projects = [key for key in kwargs [options .KEYS ] if not projects .exists (key , endpoint )]
244182 if len (non_existing_projects ) > 0 :
245183 utilities .exit_fatal (f"Project key(s) '{ ',' .join (non_existing_projects )} ' do(es) not exist" , errcodes .NO_SUCH_KEY )
246184
185+ what .append (__JSON_KEY_PLATFORM )
247186 log .info ("Exporting configuration from %s" , kwargs [options .URL ])
248187 key_list = kwargs [options .KEYS ]
249- what .append ("platform" )
250188 is_first = True
251189 q = Queue (maxsize = 0 )
252190 with utilities .open_file (file , mode = "w" ) as fd :
@@ -268,16 +206,20 @@ def __export_config_async(endpoint: platform.Platform, what: list[str], **kwargs
268206 except exceptions .UnsupportedOperation as e :
269207 log .warning (e .message )
270208 print ("\n }" , file = fd )
271- utilities .normalize_json_file (file , remove_empty = True , remove_none = True )
209+ utilities .normalize_json_file (file , remove_empty = False , remove_none = True )
272210 log .info ("Exporting migration data from %s completed" , kwargs ["url" ])
273211
274212
275- def __export_config (endpoint : platform .Platform , what : list [str ], ** kwargs ) -> None :
276- """Exports the configuration of the SonarQube platform"""
277- if kwargs [options .KEYS ] or options .WHAT_PROJECTS not in what or kwargs [options .FORMAT ] != "json" :
278- __export_config_sync (endpoint = endpoint , what = what , ** kwargs )
279- else :
280- __export_config_async (endpoint = endpoint , what = what , ** kwargs )
213+ def __prep_json_for_write (json_data : types .ObjectJsonRepr , export_settings : types .ConfigSettings ) -> types .ObjectJsonRepr :
214+ """Cleans up the JSON before writing"""
215+ json_data = utilities .sort_lists (json_data )
216+ if export_settings .get ("MODE" , "CONFIG" ) == "MIGRATION" :
217+ return json_data
218+ if not export_settings .get ("FULL_EXPORT" , False ):
219+ json_data = utilities .remove_empties (utilities .remove_nones (json_data ))
220+ if export_settings .get ("INLINE_LISTS" , True ):
221+ json_data = utilities .inline_lists (json_data , exceptions = ("conditions" ,))
222+ return json_data
281223
282224
283225def __import_config (endpoint : platform .Platform , what : list [str ], ** kwargs ) -> None :
@@ -330,7 +272,7 @@ def main() -> None:
330272 kwargs [options .FORMAT ] = utilities .deduct_format (kwargs [options .FORMAT ], kwargs [options .REPORT_FILE ], allowed_formats = ("json" , "yaml" ))
331273 if kwargs [options .EXPORT ]:
332274 try :
333- __export_config (endpoint , what , ** kwargs )
275+ export_config (endpoint , what , ** kwargs )
334276 except exceptions .ObjectNotFound as e :
335277 utilities .exit_fatal (e .message , errcodes .NO_SUCH_KEY )
336278 except (PermissionError , FileNotFoundError ) as e :
0 commit comments