Skip to content

Commit 82e742b

Browse files
authored
Merge pull request #2 from okorach/master
Solve-sonar-config-regressions (okorach#1390)
2 parents 1644ddd + f160eaa commit 82e742b

File tree

2 files changed

+69
-28
lines changed

2 files changed

+69
-28
lines changed

cli/config.py

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,15 @@
2323
"""
2424
import sys
2525
import os
26-
from threading import Lock
26+
from threading import Thread, Lock
27+
from queue import Queue
2728

2829
import json
2930
import yaml
3031

3132
from cli import options
3233
from sonar import exceptions, errcodes, utilities
34+
from sonar.util import types
3335
import sonar.logging as log
3436
from sonar import platform, rules, qualityprofiles, qualitygates, users, groups
3537
from sonar import projects, portfolios, applications
@@ -219,44 +221,84 @@ def __export_config_sync(endpoint: platform.Platform, what: list[str], **kwargs)
219221
log.info("Synchronous export of configuration from %s completed", kwargs["url"])
220222

221223

224+
def write_objects(queue: Queue, fd, object_type: str, export_settings: types.ConfigSettings) -> None:
225+
"""
226+
Thread to write projects in the JSON file
227+
"""
228+
done = False
229+
prefix = ""
230+
log.info("Waiting %s to write...", object_type)
231+
print(f'"{object_type}": ' + "{", file=fd)
232+
while not done:
233+
obj_json = queue.get()
234+
done = obj_json is None
235+
if not done:
236+
if export_settings.get("INLINE_LISTS", True):
237+
obj_json = utilities.inline_lists(obj_json, exceptions=("conditions",))
238+
if object_type in ("projects", "applications", "portfolios", "users"):
239+
if object_type == "users":
240+
key = obj_json.pop("login", None)
241+
else:
242+
key = obj_json.pop("key", None)
243+
log.debug("Writing %s key '%s'", object_type[:-1], key)
244+
print(f'{prefix}"{key}": {utilities.json_dump(obj_json)}', end="", file=fd)
245+
else:
246+
log.debug("Writing %s", object_type)
247+
print(f"{prefix}{utilities.json_dump(obj_json)[2:-1]}", end="", file=fd)
248+
prefix = ",\n"
249+
queue.task_done()
250+
print("\n}", file=fd, end="")
251+
log.info("Writing %s complete", object_type)
252+
253+
222254
def __export_config_async(endpoint: platform.Platform, what: list[str], **kwargs) -> None:
223255
"""Exports a platform configuration in a JSON file"""
256+
file = kwargs[options.REPORT_FILE]
224257
export_settings = {
225258
"INLINE_LISTS": not kwargs["dontInlineLists"],
226-
"EXPORT_DEFAULTS": kwargs["exportDefaults"],
227-
"FULL_EXPORT": kwargs["fullExport"],
259+
"EXPORT_DEFAULTS": True,
260+
# "FULL_EXPORT": kwargs["fullExport"],
261+
"FULL_EXPORT": False,
262+
"MODE": "MIGRATION",
228263
"THREADS": kwargs[options.NBR_THREADS],
229-
options.REPORT_FILE: kwargs[options.REPORT_FILE],
230-
"WRITE_CALLBACK": write_project,
264+
"SKIP_ISSUES": True,
231265
}
232-
log.info("Exporting configuration from %s (asynchronously)", kwargs[options.URL])
266+
if "projects" in what and kwargs[options.KEYS]:
267+
non_existing_projects = [key for key in kwargs[options.KEYS] if not projects.exists(key, endpoint)]
268+
if len(non_existing_projects) > 0:
269+
utilities.exit_fatal(f"Project key(s) '{','.join(non_existing_projects)}' do(es) not exist", errcodes.NO_SUCH_KEY)
270+
271+
log.info("Exporting configuration from %s", kwargs[options.URL])
233272
key_list = kwargs[options.KEYS]
234273
sq_settings = {__JSON_KEY_PLATFORM: endpoint.basics()}
235-
for what_item, call_data in _EXPORT_CALLS.items():
236-
if what_item not in what or what_item == options.WHAT_PROJECTS:
237-
continue
238-
ndx, func = call_data
239-
try:
240-
sq_settings[ndx] = utilities.remove_empties(func(endpoint, export_settings=export_settings, key_list=key_list))
241-
__write_export(sq_settings, kwargs[options.REPORT_FILE], kwargs[options.FORMAT])
242-
except exceptions.UnsupportedOperation as e:
243-
log.warning(e.message)
244-
except exceptions.ObjectNotFound as e:
245-
log.error(e.message)
246-
if not kwargs["dontInlineLists"]:
247-
sq_settings = utilities.inline_lists(sq_settings, exceptions=("conditions",))
248-
__write_export(sq_settings, kwargs[options.REPORT_FILE], kwargs[options.FORMAT])
249-
250-
__remove_chars_at_end(kwargs[options.REPORT_FILE], 3)
251-
__add_project_header(kwargs[options.REPORT_FILE])
252-
projects.export(endpoint, export_settings=export_settings, key_list=None)
253-
__add_project_footer(kwargs[options.REPORT_FILE])
254-
log.info("Asynchronous export of configuration from %s completed", kwargs["url"])
274+
is_first = True
275+
q = Queue(maxsize=0)
276+
with utilities.open_file(file, mode="w") as fd:
277+
print("{", file=fd)
278+
for what_item, call_data in _EXPORT_CALLS.items():
279+
if what_item not in what:
280+
continue
281+
ndx, func = call_data
282+
try:
283+
if not is_first:
284+
print(",", file=fd)
285+
is_first = False
286+
worker = Thread(target=write_objects, args=(q, fd, ndx, export_settings))
287+
worker.daemon = True
288+
worker.name = f"Write{ndx[:1].upper()}{ndx[1:10]}"
289+
worker.start()
290+
sq_settings[ndx] = func(endpoint, export_settings=export_settings, key_list=key_list, write_q=q)
291+
q.join()
292+
except exceptions.UnsupportedOperation as e:
293+
log.warning(e.message)
294+
sq_settings = utilities.remove_empties(sq_settings)
295+
print("\n}", file=fd)
296+
log.info("Exporting migration data from %s completed", kwargs["url"])
255297

256298

257299
def __export_config(endpoint: platform.Platform, what: list[str], **kwargs) -> None:
258300
"""Exports the configuration of the SonarQube platform"""
259-
if kwargs[options.KEYS] or options.WHAT_PROJECTS not in what or kwargs[options.FORMAT] != "json" or not kwargs[options.REPORT_FILE]:
301+
if kwargs[options.KEYS] or options.WHAT_PROJECTS not in what or kwargs[options.FORMAT] != "json":
260302
__export_config_sync(endpoint=endpoint, what=what, **kwargs)
261303
else:
262304
__export_config_async(endpoint=endpoint, what=what, **kwargs)

migration/migration.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
Exports SonarQube platform configuration as JSON
2323
"""
2424
import sys
25-
import os
2625
from threading import Thread, Lock
2726
from queue import Queue
2827

0 commit comments

Comments
 (0)