From 2825247960c55436a4bbadd8e7fdd019381c3ba3 Mon Sep 17 00:00:00 2001 From: Olivier Korach Date: Sat, 12 Oct 2024 11:03:42 +0200 Subject: [PATCH 1/8] Log all HTTP errors --- cli/findings_export.py | 8 +++---- cli/loc.py | 4 ++-- cli/measures_export.py | 12 ++-------- sonar/app_branches.py | 7 +++++- sonar/applications.py | 6 +++++ sonar/branches.py | 16 +++++++++---- sonar/devops.py | 1 + sonar/hotspots.py | 1 + sonar/issues.py | 20 +++++++++------- sonar/measures.py | 2 ++ sonar/organizations.py | 1 + sonar/permissions/permission_templates.py | 3 ++- sonar/permissions/permissions.py | 2 +- sonar/platform.py | 24 +++++++++++-------- sonar/portfolio_reference.py | 4 +++- sonar/portfolios.py | 9 +++++--- sonar/projects.py | 28 +++++++++++++---------- sonar/qualitygates.py | 2 ++ sonar/qualityprofiles.py | 2 +- sonar/rules.py | 1 + sonar/settings.py | 4 +++- sonar/sqobject.py | 3 ++- sonar/utilities.py | 13 +++++------ 23 files changed, 106 insertions(+), 67 deletions(-) diff --git a/cli/findings_export.py b/cli/findings_export.py index 13afcf133..f4172d417 100755 --- a/cli/findings_export.py +++ b/cli/findings_export.py @@ -295,7 +295,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ component.endpoint, component.key, branch=params.get("branch", None), pull_request=params.get("pullRequest", None) ) except HTTPError as e: - log.critical("Error %s while exporting findings of %s, skipped", str(e), str(component)) + log.critical("%s while exporting findings of %s, skipped", util.http_error(e), str(component)) findings_list = {} write_queue.put([findings_list, False]) else: @@ -324,7 +324,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ try: findings_list = component.get_issues(filters=new_params) except HTTPError as e: - log.critical("Error %s while exporting issues of %s, skipped", str(e), str(component)) + log.critical("%s while exporting issues of %s, skipped", util.http_error(e), str(component)) findings_list = {} else: log.debug("Status = %s, Types = %s, Resol = %s, Sev = %s", str(i_statuses), str(i_types), str(i_resols), str(i_sevs)) @@ -334,7 +334,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ try: findings_list.update(component.get_hotspots(filters=new_params)) except HTTPError as e: - log.critical("Error %s while exporting hotspots of object key %s, skipped", str(e), str(component)) + log.critical("%s while exporting hotspots of object key %s, skipped", util.http_error(e), str(component)) else: log.debug("Status = %s, Types = %s, Resol = %s, Sev = %s", str(h_statuses), str(h_types), str(h_resols), str(h_sevs)) log.info("Selected types, severities, resolutions or statuses disables issue search") @@ -352,7 +352,7 @@ def store_findings(components_list: dict[str, object], params: ConfigSettings) - log.debug("Queue %s task %s put", str(my_queue), str(comp)) my_queue.put((comp, params.copy())) except HTTPError as e: - log.critical("Error %s while exporting findings of %s, skipped", str(e), str(comp)) + log.critical("%s while exporting findings of %s, skipped", util.http_error(e), str(comp)) threads = params.get(options.NBR_THREADS, 4) for i in range(min(threads, len(components_list))): diff --git a/cli/loc.py b/cli/loc.py index 71ee67724..9a3c8b8db 100644 --- a/cli/loc.py +++ b/cli/loc.py @@ -52,7 +52,7 @@ def __get_csv_row(o: object, **kwargs) -> tuple[list[str], str]: try: loc = o.loc() except HTTPError as e: - log.warning("HTTP Error %s, LoC export of %s skipped", str(e), str(o)) + log.warning("%s, LoC export of %s skipped", util.http_error(e), str(o)) loc = "" arr = [o.key, loc] obj_type = type(o).__name__.lower() @@ -114,7 +114,7 @@ def __get_object_json_data(o: object, **kwargs) -> dict[str, str]: try: d["ncloc"] = o.loc() except HTTPError as e: - log.warning("HTTP Error %s, LoC export of %s skipped", str(e), str(o)) + log.warning("%s, LoC export of %s skipped", util.http_error(e), str(o)) if kwargs[options.WITH_NAME]: d[f"{parent_type}Name"] = o.name if obj_type in ("branch", "applicationbranch"): diff --git a/cli/measures_export.py b/cli/measures_export.py index 99321b5b8..0c2d03298 100755 --- a/cli/measures_export.py +++ b/cli/measures_export.py @@ -56,12 +56,7 @@ def __last_analysis(component: object) -> str: def __get_json_measures_history(obj: object, wanted_metrics: types.KeyList) -> dict[str, str]: """Returns the measure history of an object (project, branch, application, portfolio)""" - data = {} - try: - data["history"] = obj.get_measures_history(wanted_metrics) - except HTTPError as e: - log.error("HTTP Error %s, measures history export of %s skipped", str(e), str(obj)) - return data + return {"history": obj.get_measures_history(wanted_metrics)} def __get_object_measures(obj: object, wanted_metrics: types.KeyList) -> dict[str, str]: @@ -289,10 +284,7 @@ def __get_measures(obj: object, wanted_metrics: types.KeyList, hist: bool) -> Un else: data.update(__get_object_measures(obj, wanted_metrics)) except HTTPError as e: - if e.response.status_code == HTTPStatus.FORBIDDEN: - log.error("Insufficient permission to retrieve measures of %s, export skipped for this object", str(obj)) - else: - log.error("HTTP Error %s while retrieving measures of %s, export skipped for this object", str(e), str(obj)) + log.error("%s, measures export skipped for %s", util.http_error(e), str(obj)) return None return data diff --git a/sonar/app_branches.py b/sonar/app_branches.py index ddf55b49b..90fafe0c8 100644 --- a/sonar/app_branches.py +++ b/sonar/app_branches.py @@ -34,7 +34,7 @@ from sonar.applications import Application as App from sonar.branches import Branch -from sonar import exceptions, projects +from sonar import exceptions, projects, utilities import sonar.sqobject as sq _OBJECTS = {} @@ -112,6 +112,8 @@ def create(cls, app: App, name: str, project_branches: list[Branch]) -> Applicat except HTTPError as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(f"app.App {app.key} branch '{name}", e.response.text) + log.critical("%s while creating branch '%s' of '%s'", utilities.http_error(e), name, str(app)) + raise return ApplicationBranch(app=app, name=name, project_branches=project_branches) @classmethod @@ -185,6 +187,9 @@ def update(self, name: str, project_branches: list[Branch]) -> bool: except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(str(self), e.response.text) + log.critical("%s while updating '%s'", utilities.http_error(e), str(self)) + raise + self.name = name self._project_branches = project_branches return ok diff --git a/sonar/applications.py b/sonar/applications.py index b09e7402c..28d03e63c 100644 --- a/sonar/applications.py +++ b/sonar/applications.py @@ -93,6 +93,8 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Application: except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key, f"Application key '{key}' not found") + log.critical("%s while getting app key '%s'", util.http_error(e), key) + raise return cls.load(endpoint, data) @classmethod @@ -134,6 +136,8 @@ def create(cls, endpoint: pf.Platform, key: str, name: str) -> Application: except HTTPError as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(key, e.response.text) + log.critical("%s while creating app key '%s'", util.http_error(e), key) + raise return Application(endpoint, key, name) def refresh(self) -> None: @@ -150,6 +154,7 @@ def refresh(self) -> None: if e.response.status_code == HTTPStatus.NOT_FOUND: _OBJECTS.pop(self.uuid(), None) raise exceptions.ObjectNotFound(self.key, f"{str(self)} not found") + log.critical("%s while refreshing %s", util.http_error(e), str(self)) raise def __str__(self) -> str: @@ -388,6 +393,7 @@ def add_projects(self, project_list: list[str]) -> bool: log.warning("Project '%s' not found, can't be added to %s", proj, self) ok = False else: + log.critical("%s while adding projects to %s", util.http_error(e), str(self)) raise return ok diff --git a/sonar/branches.py b/sonar/branches.py index f043adb44..ce920025f 100644 --- a/sonar/branches.py +++ b/sonar/branches.py @@ -92,6 +92,8 @@ def get_object(cls, concerned_object: projects.Project, branch_name: str) -> Bra except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"Project '{concerned_object.key}' not found") + log.critical("%s while getting branch '%s' of %s", util.http_error(e), branch_name, str(concerned_object)) + raise for br in data.get("branches", []): if br["name"] == branch_name: return cls.load(concerned_object, branch_name, br) @@ -130,6 +132,8 @@ def refresh(self) -> Branch: except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.key, f"{str(self)} not found in SonarQube") + log.critical("%s while refreshing %s", util.http_error(e), str(self)) + raise for br in data.get("branches", []): if br["name"] == self.name: self._load(br) @@ -173,7 +177,7 @@ def is_main(self): self.refresh() return self._is_main - def delete(self): + def delete(self) -> bool: """Deletes a branch :raises ObjectNotFound: Branch not found for deletion @@ -185,6 +189,8 @@ def delete(self): except HTTPError as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: log.warning("Can't delete %s, it's the main branch", str(self)) + else: + log.critical("%s while deleting %s", util.http_error(e), str(self)) return False def new_code(self) -> str: @@ -200,8 +206,7 @@ def new_code(self) -> str: except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.concerned_object.key, f"{str(self.concerned_object)} not found") - if e.response.status_code == HTTPStatus.FORBIDDEN: - log.error("Error 403 when getting new code period of %s", {str(self)}) + log.error("%s while getting new code period of %s", util.http_error(e), str(self)) raise e for b in data["newCodePeriods"]: new_code = settings.new_code_to_string(b) @@ -264,6 +269,8 @@ def rename(self, new_name): except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.concerned_object.key, f"str{self.concerned_object} not found") + log.error("%s while renaming %s", util.http_error(e), str(self)) + raise _OBJECTS.pop(self.uuid(), None) self.name = new_name _OBJECTS[self.uuid()] = self @@ -361,8 +368,7 @@ def audit(self, audit_settings: types.ConfigSettings) -> list[Problem]: except HTTPError as e: if e.response.status_code == HTTPStatus.FORBIDDEN: log.error("Not enough permission to fully audit %s", str(self)) - else: - log.error("HTTP error %s while auditing %s", str(e), str(self)) + log.error("%s while auditing %s, audit skipped", util.http_error(e), str(self)) else: log.debug("Branch audit disabled, skipping audit of %s", str(self)) return [] diff --git a/sonar/devops.py b/sonar/devops.py index 61cb20711..188aa4831 100644 --- a/sonar/devops.py +++ b/sonar/devops.py @@ -113,6 +113,7 @@ def create(cls, endpoint: platform.Platform, key: str, plt_type: str, url_or_wor if e.response.status_code == HTTPStatus.BAD_REQUEST and endpoint.edition() in ("community", "developer"): log.warning("Can't set DevOps platform '%s', don't you have more that 1 of that type?", key) raise exceptions.UnsupportedOperation(f"Can't set DevOps platform '{key}', don't you have more that 1 of that type?") + log.error("%s while creating devops platform %s/%s/%s", util.http_error(e), key, plt_type, url_or_workspace) raise o = DevopsPlatform(endpoint=endpoint, key=key, platform_type=plt_type) o.refresh() diff --git a/sonar/hotspots.py b/sonar/hotspots.py index f35479b83..41580a494 100644 --- a/sonar/hotspots.py +++ b/sonar/hotspots.py @@ -407,6 +407,7 @@ def search(endpoint: pf.Platform, filters: types.ApiParams = None) -> dict[str, log.warning("No hotspots found with search params %s", str(inline_filters)) nbr_hotspots = 0 return {} + log.error("%s while searching hotspots", util.http_error(e)) raise e nbr_pages = util.nbr_pages(data) log.debug("Number of hotspots: %d - Page: %d/%d", nbr_hotspots, inline_filters["p"], nbr_pages) diff --git a/sonar/issues.py b/sonar/issues.py index 020c06019..e30b602a9 100644 --- a/sonar/issues.py +++ b/sonar/issues.py @@ -733,7 +733,7 @@ def __search_thread(queue: Queue) -> None: issue_list[i["key"]] = get_object(endpoint=endpoint, key=i["key"], data=i) log.debug("Added %d issues in threaded search page %d", len(data["issues"]), page) except HTTPError as e: - log.critical("HTTP Error while searching issues, search may be incomplete: %s", str(e)) + log.error("%s while searching issues, search may be incomplete", util.http_error(e)) queue.task_done() @@ -794,6 +794,7 @@ def search(endpoint: pf.Platform, params: ApiParams = None, raise_error: bool = worker.setDaemon(True) worker.start() q.join() + log.debug("Issue search for %s completed with %d issues", str(params), len(issue_list)) return issue_list @@ -849,13 +850,16 @@ def count_by_rule(endpoint: pf.Platform, **kwargs) -> dict[str, int]: rulecount = {} for i in range(nbr_slices): params["rules"] = ",".join(ruleset[i * SLICE_SIZE : min((i + 1) * SLICE_SIZE - 1, len(ruleset))]) - data = json.loads(endpoint.get(Issue.SEARCH_API, params=params).text)["facets"][0]["values"] - for d in data: - if d["val"] not in ruleset: - continue - if d["val"] not in rulecount: - rulecount[d["val"]] = 0 - rulecount[d["val"]] += d["count"] + try: + data = json.loads(endpoint.get(Issue.SEARCH_API, params=params).text)["facets"][0]["values"] + for d in data: + if d["val"] not in ruleset: + continue + if d["val"] not in rulecount: + rulecount[d["val"]] = 0 + rulecount[d["val"]] += d["count"] + except HTTPError as e: + log.warning("%s while counting issues per rule, count may be incomplete", util.http_error(e)) return rulecount diff --git a/sonar/measures.py b/sonar/measures.py index 397e1356d..94612fcd0 100644 --- a/sonar/measures.py +++ b/sonar/measures.py @@ -127,6 +127,7 @@ def get(concerned_object: object, metrics_list: KeyList, **kwargs) -> dict[str, except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"{str(concerned_object)} not found") + log.error("%s while getting measures %s of %s", util.http_error(e), str(metrics_list), str(concerned_object)) raise e m_dict = {m: None for m in metrics_list} for m in data["component"]["measures"]: @@ -157,6 +158,7 @@ def get_history(concerned_object: object, metrics_list: KeyList, **kwargs) -> li except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"{str(concerned_object)} not found") + log.error("%s while getting measures %s history of %s", util.http_error(e), str(metrics_list), str(concerned_object)) raise e res_list = [] # last_metric, last_date = "", "" diff --git a/sonar/organizations.py b/sonar/organizations.py index b323e03f9..6c7b94b07 100644 --- a/sonar/organizations.py +++ b/sonar/organizations.py @@ -82,6 +82,7 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Organization: except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key, f"Organization '{key}' not found") + log.error("%s getting organization %s", util.http_error(e), key) raise e if len(data["organizations"]) == 0: raise exceptions.ObjectNotFound(key, f"Organization '{key}' not found") diff --git a/sonar/permissions/permission_templates.py b/sonar/permissions/permission_templates.py index 548ad343a..0ceda633d 100644 --- a/sonar/permissions/permission_templates.py +++ b/sonar/permissions/permission_templates.py @@ -142,7 +142,8 @@ def set_as_default(self, what_list: list[str]) -> None: try: self.post("permissions/set_default_template", params={"templateId": self.key, "qualifier": qual}) except HTTPError as e: - log.error("HTTP Error: %s", utilities.sonar_error(e.response)) + log.error("%s while setting %s as default", utilities.http_error(e), str(self)) + raise def set_pattern(self, pattern: str) -> PermissionTemplate: """Sets a permission template pattern""" diff --git a/sonar/permissions/permissions.py b/sonar/permissions/permissions.py index 7f2c46cea..708c420b6 100644 --- a/sonar/permissions/permissions.py +++ b/sonar/permissions/permissions.py @@ -260,7 +260,7 @@ def _post_api(self, api: str, set_field: str, perms_dict: types.JsonPermissions, try: r = self.endpoint.post(api, params=params) except HTTPError as e: - log.error("HTTP Error: %s", utilities.sonar_error(e.response)) + log.error("%s while setting permissions %s", utilities.http_error(e), str(self)) result = result and r.ok return result diff --git a/sonar/platform.py b/sonar/platform.py index a06ca4d2b..ba09bf0db 100644 --- a/sonar/platform.py +++ b/sonar/platform.py @@ -52,7 +52,6 @@ WRONG_CONFIG_MSG = "Audit config property %s has wrong value %s, skipping audit" _NON_EXISTING_SETTING_SKIPPED = "Setting %s does not exist, skipping..." -_HTTP_ERROR = "%s Error: %s HTTP status code %d - %s" _SONAR_TOOLS_AGENT = f"sonar-tools {version.PACKAGE_VERSION}" _UPDATE_CENTER = "https://raw.githubusercontent.com/SonarSource/sonar-update-center-properties/master/update-center-source.properties" @@ -106,6 +105,7 @@ def verify_connection(self) -> None: try: self.get("server/version") except HTTPError as e: + log.critical("%s while verifying connection", util.http_error(e)) raise exceptions.ConnectionError(util.sonar_error(e.response)) def version(self) -> tuple[int, int, int]: @@ -247,15 +247,12 @@ def __run_request( if retry: self.url = new_url r.raise_for_status() - except requests.exceptions.HTTPError as e: + except HTTPError as e: if exit_on_error: # or (r.status_code not in mute and r.status_code not in _NORMAL_HTTP_ERRORS): - util.log_and_exit(r) + log_and_exit(e) else: - _, msg = util.http_error(r) - lvl = log.ERROR - if r.status_code in mute: - lvl = log.DEBUG - log.log(lvl, _HTTP_ERROR, req_type, self.__urlstring(api, params), r.status_code, msg) + lvl = log.DEBUG if r.status_code in mute else log.ERROR + log.log(lvl, "%s (%s request)", util.http_error(e), req_type) raise e except requests.exceptions.Timeout as e: util.exit_fatal(str(e), errcodes.HTTP_TIMEOUT) @@ -292,6 +289,7 @@ def sys_info(self) -> dict[str, any]: time.sleep(0.5) counter += 1 else: + log.critical("%s while getting system info", util.http_error(e)) raise e self.__sys_info = json.loads(resp.text) success = True @@ -811,7 +809,7 @@ def __lta_and_latest() -> tuple[tuple[int, int, int], tuple[int, int, int]]: v.append("0") LATEST = tuple(int(n) for n in v) log.debug("Sonar update center says LTA (ex-LTS) = %s, LATEST = %s", str(LTA), str(LATEST)) - except (EnvironmentError, requests.exceptions.HTTPError): + except (EnvironmentError, HTTPError): LTA = _HARDCODED_LTA LATEST = _HARDCODED_LATEST log.debug("Sonar update center read failed, hardcoding LTA (ex-LTS) = %s, LATEST = %s", str(LTA), str(LATEST)) @@ -899,3 +897,11 @@ def basics( write_q.put(exp) write_q.put(None) return exp + + +def log_and_exit(exception: requests.exceptions.HTTPError) -> None: + """If HTTP response is not OK, display an error log and exit""" + err_code, msg = util.http_error_and_code(exception) + if err_code is None: + return + util.exit_fatal(msg, err_code) diff --git a/sonar/portfolio_reference.py b/sonar/portfolio_reference.py index 7fba42b91..1e3ad3645 100644 --- a/sonar/portfolio_reference.py +++ b/sonar/portfolio_reference.py @@ -31,7 +31,7 @@ import sonar.platform as pf from sonar.util import types -from sonar import exceptions +from sonar import exceptions, utilities import sonar.sqobject as sq _OBJECTS = {} @@ -76,6 +76,8 @@ def create(cls, reference: object, parent: object, params: types.ApiParams = Non except HTTPError as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists + log.critical("%s while creating portfolio reference to %s in %s", utilities.http_error(e), str(reference), str(parent)) + raise e return PortfolioReference(reference=reference, parent=parent) def __str__(self) -> str: diff --git a/sonar/portfolios.py b/sonar/portfolios.py index c2ae5f9a1..9c7b25d58 100644 --- a/sonar/portfolios.py +++ b/sonar/portfolios.py @@ -264,6 +264,7 @@ def add_reference_subportfolio(self, reference: Portfolio) -> object: self.post("views/add_local_view", params={"key": self.key, "ref_key": reference.key}, mute=(HTTPStatus.BAD_REQUEST,)) except HTTPError as e: if e.response.status_code != HTTPStatus.BAD_REQUEST: + log.error("%s while adding reference subportfolio to %s", util.http_error(e), str(self)) raise self._sub_portfolios.update({reference.key: ref}) return ref @@ -276,6 +277,7 @@ def add_standard_subportfolio(self, key: str, name: str, **kwargs) -> Portfolio: self.post("views/add_sub_view", params={"key": self.key, "name": name, "subKey": key}, mute=(HTTPStatus.BAD_REQUEST,)) except HTTPError as e: if e.response.status_code != HTTPStatus.BAD_REQUEST: + log.error("%s while adding standard subportfolio to %s", util.http_error(e), str(self)) raise self._sub_portfolios.update({subp.key: subp}) return subp @@ -431,6 +433,7 @@ def add_project_branches(self, branch_dict: dict[str, Union[str, object]]) -> Po # Project or branch already in portfolio pass else: + log.error("%s while adding project branches to %s", util.http_error(e), str(self)) raise return self @@ -522,6 +525,7 @@ def add_application_branch(self, app_key: str, branch: str = settings.DEFAULT_BR self.post("views/add_application_branch", params=params, mute=(HTTPStatus.BAD_REQUEST,)) except HTTPError as e: if e.response.status_code != HTTPStatus.BAD_REQUEST: + log.error("%s while adding application branch to %s", util.http_error(e), str(self)) raise log.warning(util.sonar_error(e.response)) if app_key not in self._applications: @@ -581,7 +585,7 @@ def get_project_list(self) -> list[str]: proj_key_list += [c["refKey"] for c in data["components"]] except HTTPError as e: if e.response.status_code in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): - log.warning("HTTP Error %s while collecting projects from %s, stopping collection", str(e), str(self)) + log.warning("%s while collecting projects from %s, stopping collection", util.http_error(e), str(self)) else: log.critical("HTTP Error %s while collecting projects from %s, proceeding anyway", str(e), str(self)) break @@ -791,8 +795,7 @@ def export( else: log.debug("Skipping export of %s, it's a standard sub-portfolio", str(p)) except HTTPError as e: - _, msg = util.http_error(e.response) - log.error("%s while exporting %s, export will be empty for this portfolio", msg, str(p)) + log.error("%s while exporting %s, export will be empty for this portfolio", util.http_error(e), str(p)) exported_portfolios[k] = {} i += 1 if i % 10 == 0 or i == nb_portfolios: diff --git a/sonar/projects.py b/sonar/projects.py index 0c3fa3c47..3ce10fa40 100644 --- a/sonar/projects.py +++ b/sonar/projects.py @@ -170,6 +170,7 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Project: return cls.load(endpoint, data["components"][0]) except HTTPError as e: if e.response.status_code != HTTPStatus.FORBIDDEN: + log.error("%s while getting project '%s'", util.http_error(e), key) raise data = json.loads(endpoint.get(_NAV_API, params={"component": key}).text) if "errors" in data: @@ -210,6 +211,8 @@ def create(cls, endpoint: pf.Platform, key: str, name: str) -> Project: except HTTPError as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(key, e.response.text) + log.error("%s while creating project '%s'", util.http_error(e), key) + raise o = cls(endpoint, key) o.name = name return o @@ -382,7 +385,7 @@ def binding(self): # Hack: 8.9 returns 404, 9.x returns 400 self._binding["has_binding"] = False else: - log.error("alm_settings/get_binding returning status code %d", e.response.status_code) + log.error("%s while getting '%s' bindinfs", util.http_error(e), str(self)) raise e log.debug("Binding = %s", util.json_dump(self._binding["binding"])) return self._binding["binding"] @@ -560,8 +563,7 @@ def __audit_binding_valid(self, audit_settings: types.ConfigSettings) -> list[Pr # Hack: 8.9 returns 404, 9.x returns 400 if e.response.status_code in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): return [Problem(get_rule(RuleId.PROJ_INVALID_BINDING), self, str(self))] - else: - util.exit_fatal(f"alm_settings/validate_binding returning status code {e.response.status_code}, exiting", errcodes.SONAR_API) + log.error("%s while auditing %s binding, skipped", util.http_error(e), str(self)) return [] def get_type(self) -> str: @@ -617,8 +619,8 @@ def ci(self) -> str: data = json.loads(self.get("project_analyses/search", params={"project": self.key, "ps": 1}).text)["analyses"] if len(data) > 0: self._ci, self._revision = data[0].get("detectedCI", "unknown"), data[0].get("revision", "unknown") - except HTTPError: - log.warning("HTTP Error, can't retrieve CI tool and revision") + except HTTPError as e: + log.warning("%s while getting %s CI tool", util.http_error(e), str(self)) except KeyError: log.warning("KeyError, can't retrieve CI tool and revision") return self._ci @@ -668,7 +670,7 @@ def audit(self, audit_settings: types.ConfigSettings) -> list[Problem]: if e.response.status_code == HTTPStatus.FORBIDDEN: log.error("Not enough permission to fully audit %s", str(self)) else: - log.error("HTTP error %s while auditing %s", str(e), str(self)) + log.error("%s while auditing %s", util.http_error(e), str(self)) return problems def export_zip(self, timeout: int = 180) -> dict[str, str]: @@ -706,8 +708,9 @@ def export_async(self) -> Union[str, None]: log.info("Exporting %s (asynchronously)", str(self)) try: return json.loads(self.post("project_dump/export", params={"key": self.key}).text)["taskId"] - except HTTPError: - return None + except HTTPError as e: + log.error("%s while exporting zip of %s CI", util.http_error(e), str(self)) + return None def import_zip(self) -> bool: """Imports a project zip file in SonarQube @@ -1051,13 +1054,13 @@ def export(self, export_settings: types.ConfigSettings, settings_list: dict[str, log.critical("Insufficient privileges to access %s, export of this project interrupted", str(self)) json_data["error"] = "Insufficient permissions while exporting project, export interrupted" else: - log.critical("HTTP error %s while exporting %s, export of this project interrupted", str(e), str(self)) + log.critical("%s while exporting %s, export of this project interrupted", util.http_error(e), str(self)) json_data["error"] = f"HTTP error {str(e)} while extracting project" except ConnectionError as e: - log.critical("Connecting error %s while exporting %s, export of this project interrupted", str(self), str(e)) + log.critical("Connecting error %s while exporting %s, export of this project interrupted", str(e), str(self)) json_data["error"] = f"Connection error {str(e)} while extracting project, export interrupted" except Exception as e: - log.critical("Connecting error %s while exporting %s, export of this project interrupted", str(self), str(e)) + log.critical("Exception %s while exporting %s, export of this project interrupted", str(e), str(self)) json_data["error"] = f"Exception {str(e)} while exporting project, export interrupted" log.debug("Exporting %s done", str(self)) return util.remove_nones(json_data) @@ -1093,6 +1096,7 @@ def set_permissions(self, desired_permissions: types.ObjectJsonRepr) -> bool: return True except HTTPError as e: if e.response.status_code != HTTPStatus.BAD_REQUEST: + log.error("%s while setting permissions of %s", util.http_error(e), str(self)) raise e log.error(util.sonar_error(e.response)) return False @@ -1433,7 +1437,7 @@ def __audit_thread(queue: Queue[Project], results: list[Problem], audit_settings if e.response.status_code == HTTPStatus.FORBIDDEN: log.error("Not enough permission to fully audit %s", str(project)) else: - log.error("HTTP error %s while auditing %s", str(e), str(project)) + log.error("%s while auditing %s", util.http_error(e), str(project)) queue.task_done() log.debug("%s audit complete", str(project)) log.debug("Queue empty, exiting thread") diff --git a/sonar/qualitygates.py b/sonar/qualitygates.py index 265bba8f0..9b3f64e4d 100644 --- a/sonar/qualitygates.py +++ b/sonar/qualitygates.py @@ -176,6 +176,8 @@ def projects(self) -> dict[str, projects.Project]: except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.name, f"{str(self)} not found") + log.error("%s while getting %s projects", util.http_error(e), str(self)) + raise data = json.loads(resp.text) for prj in data["results"]: log.info("Proj = %s", str(prj)) diff --git a/sonar/qualityprofiles.py b/sonar/qualityprofiles.py index 39dcc4301..6df52ea11 100644 --- a/sonar/qualityprofiles.py +++ b/sonar/qualityprofiles.py @@ -285,7 +285,7 @@ def activate_rules(self, ruleset: dict[str, str]) -> bool: ok = ok and self.activate_rule(rule_key=r_key, severity=sev) except HTTPError as e: ok = False - log.warning("Activation of rule '%s' in %s failed: HTTP Error %d", r_key, str(self), e.response.status_code) + log.error("%s while activating rules in '%s'", util.http_error(e), r_key) return ok def update(self, data: types.ObjectJsonRepr, queue: Queue) -> QualityProfile: diff --git a/sonar/rules.py b/sonar/rules.py index 37ffe7ec7..fde05d316 100644 --- a/sonar/rules.py +++ b/sonar/rules.py @@ -134,6 +134,7 @@ def get_object(cls, endpoint: platform.Platform, key: str) -> Rule: except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key=key, message=f"Rule key '{key}' does not exist") + log.error("%s while getting rule'%s'", utilities.http_error(e), key) return Rule(endpoint=endpoint, key=key, data=json.loads(r.text)["rule"]) @classmethod diff --git a/sonar/settings.py b/sonar/settings.py index d0ac23142..ed82c491a 100644 --- a/sonar/settings.py +++ b/sonar/settings.py @@ -457,6 +457,7 @@ def set_new_code_period(endpoint: pf.Platform, nc_type: str, nc_value: str, proj except HTTPError as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.UnsupportedOperation(f"Can't set project new code period: {e.response.text}") + log.error("%s setting new code period of '%s'", util.http_error(e), str(project_key)) raise return ok @@ -489,6 +490,7 @@ def set_visibility(endpoint: pf.Platform, visibility: str, component: object = N except HTTPError as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.UnsupportedOperation(f"Can't set project default visibility: {e.response.text}") + log.error("%s setting new code period of '%s'", util.http_error(e), str(component)) raise @@ -502,7 +504,7 @@ def set_setting(endpoint: pf.Platform, key: str, value: any, component: object = try: s.set(value) except HTTPError as e: - log.error("Setting '%s' cannot be set: %s", key, util.sonar_error(e.response)) + log.error("%s while setting setting '%s'", util.http_error(e), key, str(component)) return False except exceptions.UnsupportedOperation as e: log.error("Setting '%s' cannot be set: %s", key, e.message) diff --git a/sonar/sqobject.py b/sonar/sqobject.py index f8605bf72..977841427 100644 --- a/sonar/sqobject.py +++ b/sonar/sqobject.py @@ -117,7 +117,7 @@ def __search_thread(queue: Queue) -> None: else: objects[obj[key_field]] = object_class(endpoint, obj[key_field], data=obj) except HTTPError as e: - log.critical("HTTP error while searching %s, search skipped: %s", object_class.__name__, str(e)) + log.critical("%s while searching %s, search skipped", utilities.http_error(e), object_class.__name__) queue.task_done() @@ -167,6 +167,7 @@ def delete_object(object: SqObject, api: str, params: types.ApiParams, map: dict if e.response.status_code == HTTPStatus.NOT_FOUND: map.pop(object.uuid(), None) raise exceptions.ObjectNotFound(object.key, f"{str(object)} not found for delete") + log.error("%s while deleting object '%s'", utilities.http_error(e), str(object)) raise diff --git a/sonar/utilities.py b/sonar/utilities.py index 9ae910f81..309727188 100644 --- a/sonar/utilities.py +++ b/sonar/utilities.py @@ -423,8 +423,9 @@ def sonar_error(response: requests.models.Response) -> str: return "" -def http_error(response: requests.models.Response) -> tuple[str, int]: +def http_error_and_code(exception: requests.exceptions.HTTPError) -> tuple[int, str]: """Returns the Sonar error code of an API HTTP response, or None if no error""" + response = exception.response if response.ok: return None, None tool_msg = f"For request URL {response.request.url}\n" @@ -441,12 +442,10 @@ def http_error(response: requests.models.Response) -> tuple[str, int]: return err_code, f"{tool_msg}: {sonar_error(response)}" -def log_and_exit(response: requests.models.Response) -> None: - """If HTTP response is not OK, display an error log and exit""" - err_code, msg = http_error(response) - if err_code is None: - return - exit_fatal(msg, err_code) +def http_error(exception: requests.exceptions.HTTPError) -> tuple[int, str]: + """Returns the Sonar error code of an API HTTP response, or None if no error""" + _, errmsg = http_error_and_code(exception) + return errmsg def object_key(key_or_obj): From ed249903c18a9c708571e27d5b3e7d58137529bc Mon Sep 17 00:00:00 2001 From: Olivier Korach Date: Sat, 12 Oct 2024 11:11:35 +0200 Subject: [PATCH 2/8] Cleaner project export progress log status --- sonar/projects.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sonar/projects.py b/sonar/projects.py index 3ce10fa40..3f594f541 100644 --- a/sonar/projects.py +++ b/sonar/projects.py @@ -1490,9 +1490,8 @@ def __export_thread(queue: Queue[Project], results: dict[str, str], export_setti with _CLASS_LOCK: export_settings["EXPORTED"] += 1 nb, tot = export_settings["EXPORTED"], export_settings["NBR_PROJECTS"] - log.debug("%d/%d projects exported (%d%%)", nb, tot, (nb * 100) // tot) - if nb % 10 == 0 or tot - nb < 10: - log.info("%d/%d projects exported (%d%%)", nb, tot, (nb * 100) // tot) + lvl = log.INFO if nb % 10 == 0 or tot - nb < 10 else log.DEBUG + log.log(lvl, "%d/%d projects exported (%d%%)", nb, tot, (nb * 100) // tot) queue.task_done() From ac9f6c3cde12e98779ea557c6d997f8869655a01 Mon Sep 17 00:00:00 2001 From: Olivier Korach Date: Sat, 12 Oct 2024 16:03:54 +0200 Subject: [PATCH 3/8] Catch RequestException and ConnectionError everywhere --- cli/findings_export.py | 12 ++--- cli/loc.py | 6 +-- cli/measures_export.py | 5 +- sonar/app_branches.py | 8 +-- sonar/applications.py | 16 +++--- sonar/branches.py | 31 ++++++------ sonar/devops.py | 4 +- sonar/hotspots.py | 8 +-- sonar/issues.py | 10 ++-- sonar/measures.py | 10 ++-- sonar/organizations.py | 7 ++- sonar/permissions/permission_templates.py | 4 +- sonar/permissions/permissions.py | 20 ++++---- sonar/permissions/quality_permissions.py | 18 +++---- sonar/platform.py | 26 ++++++---- sonar/portfolio_reference.py | 6 +-- sonar/portfolios.py | 31 ++++++------ sonar/projects.py | 61 ++++++++++------------- sonar/qualitygates.py | 6 +-- sonar/qualityprofiles.py | 14 +++--- sonar/rules.py | 6 +-- sonar/settings.py | 16 +++--- sonar/sqobject.py | 8 +-- sonar/utilities.py | 17 ++++--- 24 files changed, 170 insertions(+), 180 deletions(-) diff --git a/cli/findings_export.py b/cli/findings_export.py index f4172d417..6890944a3 100755 --- a/cli/findings_export.py +++ b/cli/findings_export.py @@ -32,7 +32,7 @@ from queue import Queue import threading from threading import Thread -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException from cli import options from sonar.util.types import ConfigSettings @@ -294,7 +294,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ findings_list = findings.export_findings( component.endpoint, component.key, branch=params.get("branch", None), pull_request=params.get("pullRequest", None) ) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.critical("%s while exporting findings of %s, skipped", util.http_error(e), str(component)) findings_list = {} write_queue.put([findings_list, False]) @@ -323,7 +323,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ if (i_statuses or not status_list) and (i_resols or not resol_list) and (i_types or not type_list) and (i_sevs or not sev_list): try: findings_list = component.get_issues(filters=new_params) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.critical("%s while exporting issues of %s, skipped", util.http_error(e), str(component)) findings_list = {} else: @@ -333,8 +333,8 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ if (h_statuses or not status_list) and (h_resols or not resol_list) and (h_types or not type_list) and (h_sevs or not sev_list): try: findings_list.update(component.get_hotspots(filters=new_params)) - except HTTPError as e: - log.critical("%s while exporting hotspots of object key %s, skipped", util.http_error(e), str(component)) + except (HTTPError, ConnectionError, RequestException) as e: + log.error("%s while exporting hotspots of object key %s, skipped", util.http_error(e), str(component)) else: log.debug("Status = %s, Types = %s, Resol = %s, Sev = %s", str(h_statuses), str(h_types), str(h_resols), str(h_sevs)) log.info("Selected types, severities, resolutions or statuses disables issue search") @@ -351,7 +351,7 @@ def store_findings(components_list: dict[str, object], params: ConfigSettings) - try: log.debug("Queue %s task %s put", str(my_queue), str(comp)) my_queue.put((comp, params.copy())) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.critical("%s while exporting findings of %s, skipped", util.http_error(e), str(comp)) threads = params.get(options.NBR_THREADS, 4) diff --git a/cli/loc.py b/cli/loc.py index 9a3c8b8db..8217b984b 100644 --- a/cli/loc.py +++ b/cli/loc.py @@ -24,7 +24,7 @@ import sys import csv import datetime -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException from cli import options import sonar.logging as log @@ -51,7 +51,7 @@ def __get_csv_row(o: object, **kwargs) -> tuple[list[str], str]: """Returns CSV row of object""" try: loc = o.loc() - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.warning("%s, LoC export of %s skipped", util.http_error(e), str(o)) loc = "" arr = [o.key, loc] @@ -113,7 +113,7 @@ def __get_object_json_data(o: object, **kwargs) -> dict[str, str]: d = {parent_type: o.concerned_object.key, "branch": o.name, "ncloc": ""} try: d["ncloc"] = o.loc() - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.warning("%s, LoC export of %s skipped", util.http_error(e), str(o)) if kwargs[options.WITH_NAME]: d[f"{parent_type}Name"] = o.name diff --git a/cli/measures_export.py b/cli/measures_export.py index 0c2d03298..538a996a4 100755 --- a/cli/measures_export.py +++ b/cli/measures_export.py @@ -29,8 +29,7 @@ from typing import Union -from http import HTTPStatus -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException from sonar.util import types from cli import options import sonar.logging as log @@ -283,7 +282,7 @@ def __get_measures(obj: object, wanted_metrics: types.KeyList, hist: bool) -> Un data.update(__get_json_measures_history(obj, wanted_metrics)) else: data.update(__get_object_measures(obj, wanted_metrics)) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.error("%s, measures export skipped for %s", util.http_error(e), str(obj)) return None return data diff --git a/sonar/app_branches.py b/sonar/app_branches.py index 90fafe0c8..1dabc8fa2 100644 --- a/sonar/app_branches.py +++ b/sonar/app_branches.py @@ -24,7 +24,7 @@ import json from http import HTTPStatus -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException from requests.utils import quote import sonar.logging as log @@ -109,7 +109,7 @@ def create(cls, app: App, name: str, project_branches: list[Branch]) -> Applicat params["projectBranch"].append(br_name) try: app.endpoint.post(APIS["create"], params=params) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(f"app.App {app.key} branch '{name}", e.response.text) log.critical("%s while creating branch '%s' of '%s'", utilities.http_error(e), name, str(app)) @@ -184,10 +184,10 @@ def update(self, name: str, project_branches: list[Branch]) -> bool: params["projectBranch"].append(br_name) try: ok = self.endpoint.post(APIS["update"], params=params).ok - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(str(self), e.response.text) - log.critical("%s while updating '%s'", utilities.http_error(e), str(self)) + log.error("%s while updating '%s'", utilities.http_error(e), str(self)) raise self.name = name diff --git a/sonar/applications.py b/sonar/applications.py index 28d03e63c..2995df152 100644 --- a/sonar/applications.py +++ b/sonar/applications.py @@ -26,7 +26,7 @@ from datetime import datetime from http import HTTPStatus from threading import Lock -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.platform as pf @@ -90,10 +90,10 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Application: return _OBJECTS[uu] try: data = json.loads(endpoint.get(APIS["get"], params={"application": key}).text)["application"] - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key, f"Application key '{key}' not found") - log.critical("%s while getting app key '%s'", util.http_error(e), key) + log.error("%s while getting app key '%s'", util.http_error(e), key) raise return cls.load(endpoint, data) @@ -133,7 +133,7 @@ def create(cls, endpoint: pf.Platform, key: str, name: str) -> Application: check_supported(endpoint) try: endpoint.post(APIS["create"], params={"key": key, "name": name}) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(key, e.response.text) log.critical("%s while creating app key '%s'", util.http_error(e), key) @@ -150,11 +150,11 @@ def refresh(self) -> None: try: self.reload(json.loads(self.get("navigation/component", params={"component": self.key}).text)) self.reload(json.loads(self.get(APIS["get"], params=self.search_params()).text)["application"]) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: _OBJECTS.pop(self.uuid(), None) raise exceptions.ObjectNotFound(self.key, f"{str(self)} not found") - log.critical("%s while refreshing %s", util.http_error(e), str(self)) + log.error("%s while refreshing %s", util.http_error(e), str(self)) raise def __str__(self) -> str: @@ -388,12 +388,12 @@ def add_projects(self, project_list: list[str]) -> bool: try: r = self.post("applications/add_project", params={"application": self.key, "project": proj}) ok = ok and r.ok - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: log.warning("Project '%s' not found, can't be added to %s", proj, self) ok = False else: - log.critical("%s while adding projects to %s", util.http_error(e), str(self)) + log.error("%s while adding projects to %s", util.http_error(e), str(self)) raise return ok diff --git a/sonar/branches.py b/sonar/branches.py index ce920025f..c8b27f9e9 100644 --- a/sonar/branches.py +++ b/sonar/branches.py @@ -22,7 +22,7 @@ from http import HTTPStatus import json from urllib.parse import unquote -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import requests.utils from sonar import platform @@ -89,8 +89,8 @@ def get_object(cls, concerned_object: projects.Project, branch_name: str) -> Bra return _OBJECTS[uu] try: data = json.loads(concerned_object.endpoint.get(APIS["list"], params={"project": concerned_object.key}).text) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"Project '{concerned_object.key}' not found") log.critical("%s while getting branch '%s' of %s", util.http_error(e), branch_name, str(concerned_object)) raise @@ -129,11 +129,10 @@ def refresh(self) -> Branch: """ try: data = json.loads(self.get(APIS["list"], params={"project": self.concerned_object.key}).text) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.key, f"{str(self)} not found in SonarQube") - log.critical("%s while refreshing %s", util.http_error(e), str(self)) - raise + log.error("%s while refreshing %s", util.http_error(e), str(self)) for br in data.get("branches", []): if br["name"] == self.name: self._load(br) @@ -186,11 +185,11 @@ def delete(self) -> bool: """ try: return sq.delete_object(self, APIS["delete"], {"branch": self.name, "project": self.concerned_object.key}, _OBJECTS) - except HTTPError as e: - if e.response.status_code == HTTPStatus.BAD_REQUEST: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: log.warning("Can't delete %s, it's the main branch", str(self)) else: - log.critical("%s while deleting %s", util.http_error(e), str(self)) + log.error("%s while deleting %s", util.http_error(e), str(self)) return False def new_code(self) -> str: @@ -203,8 +202,8 @@ def new_code(self) -> str: elif self._new_code is None: try: data = json.loads(self.get(api=APIS["get_new_code"], params={"project": self.concerned_object.key}).text) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.concerned_object.key, f"{str(self.concerned_object)} not found") log.error("%s while getting new code period of %s", util.http_error(e), str(self)) raise e @@ -266,8 +265,8 @@ def rename(self, new_name): log.info("Renaming main branch of %s from '%s' to '%s'", str(self.concerned_object), self.name, new_name) try: self.post(APIS["rename"], params={"project": self.concerned_object.key, "name": new_name}) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.concerned_object.key, f"str{self.concerned_object} not found") log.error("%s while renaming %s", util.http_error(e), str(self)) raise @@ -365,9 +364,7 @@ def audit(self, audit_settings: types.ConfigSettings) -> list[Problem]: log.debug("Auditing %s", str(self)) try: return self.__audit_last_analysis(audit_settings) + self.__audit_zero_loc() + self.__audit_never_analyzed() - except HTTPError as e: - if e.response.status_code == HTTPStatus.FORBIDDEN: - log.error("Not enough permission to fully audit %s", str(self)) + except (HTTPError, RequestException, Exception) as e: log.error("%s while auditing %s, audit skipped", util.http_error(e), str(self)) else: log.debug("Branch audit disabled, skipping audit of %s", str(self)) diff --git a/sonar/devops.py b/sonar/devops.py index 188aa4831..feeeebb1d 100644 --- a/sonar/devops.py +++ b/sonar/devops.py @@ -23,7 +23,7 @@ from http import HTTPStatus import json -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log from sonar.util import types @@ -109,7 +109,7 @@ def create(cls, endpoint: platform.Platform, key: str, plt_type: str, url_or_wor elif plt_type == "bitbucketcloud": params.update({"clientSecret": _TO_BE_SET, "clientId": _TO_BE_SET, "workspace": url_or_workspace}) endpoint.post(_CREATE_API_BBCLOUD, params=params) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.BAD_REQUEST and endpoint.edition() in ("community", "developer"): log.warning("Can't set DevOps platform '%s', don't you have more that 1 of that type?", key) raise exceptions.UnsupportedOperation(f"Can't set DevOps platform '{key}', don't you have more that 1 of that type?") diff --git a/sonar/hotspots.py b/sonar/hotspots.py index 41580a494..d02004d29 100644 --- a/sonar/hotspots.py +++ b/sonar/hotspots.py @@ -24,7 +24,7 @@ import json import re from http import HTTPStatus -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import requests.utils import sonar.logging as log @@ -402,13 +402,13 @@ def search(endpoint: pf.Platform, filters: types.ApiParams = None) -> dict[str, try: data = json.loads(endpoint.get(Hotspot.SEARCH_API, params=inline_filters, mute=(HTTPStatus.NOT_FOUND,)).text) nbr_hotspots = util.nbr_total_elements(data) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: log.warning("No hotspots found with search params %s", str(inline_filters)) nbr_hotspots = 0 return {} log.error("%s while searching hotspots", util.http_error(e)) - raise e + break nbr_pages = util.nbr_pages(data) log.debug("Number of hotspots: %d - Page: %d/%d", nbr_hotspots, inline_filters["p"], nbr_pages) if nbr_hotspots > Hotspot.MAX_SEARCH: @@ -495,8 +495,10 @@ def post_search_filter(hotspots_dict: dict[str, Hotspot], filters: types.ApiPara lang = rules.get_object(endpoint=finding.endpoint, key=finding.rule).language if lang not in filters["languages"]: filtered_findings.pop(key, None) + # pylint: disable-next=E0606 if "createdAfter" in filters and finding.creation_date < min_date: filtered_findings.pop(key, None) + # pylint: disable-next=E0606 if "createdBefore" in filters and finding.creation_date > max_date: filtered_findings.pop(key, None) diff --git a/sonar/issues.py b/sonar/issues.py index e30b602a9..79ee42c4e 100644 --- a/sonar/issues.py +++ b/sonar/issues.py @@ -29,13 +29,13 @@ from queue import Queue from threading import Thread import requests.utils -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.platform as pf from sonar.util.types import ApiParams, ApiPayload, ObjectJsonRepr, ConfigSettings -from sonar import users, sqobject, findings, changelog, projects +from sonar import users, sqobject, findings, changelog, projects, errcodes import sonar.utilities as util API_SET_TAGS = "issues/set_tags" @@ -732,7 +732,7 @@ def __search_thread(queue: Queue) -> None: i["pullRequest"] = page_params.get("pullRequest", None) issue_list[i["key"]] = get_object(endpoint=endpoint, key=i["key"], data=i) log.debug("Added %d issues in threaded search page %d", len(data["issues"]), page) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException, Exception) as e: log.error("%s while searching issues, search may be incomplete", util.http_error(e)) queue.task_done() @@ -858,8 +858,8 @@ def count_by_rule(endpoint: pf.Platform, **kwargs) -> dict[str, int]: if d["val"] not in rulecount: rulecount[d["val"]] = 0 rulecount[d["val"]] += d["count"] - except HTTPError as e: - log.warning("%s while counting issues per rule, count may be incomplete", util.http_error(e)) + except (HTTPError, Exception, RequestException) as e: + log.error("%s while counting issues per rule, count may be incomplete", util.http_error(e)) return rulecount diff --git a/sonar/measures.py b/sonar/measures.py index 94612fcd0..714225b0e 100644 --- a/sonar/measures.py +++ b/sonar/measures.py @@ -25,7 +25,7 @@ import json import re from http import HTTPStatus -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException from sonar import metrics, exceptions from sonar.util.types import ApiPayload, ApiParams, KeyList @@ -124,8 +124,8 @@ def get(concerned_object: object, metrics_list: KeyList, **kwargs) -> dict[str, try: data = json.loads(concerned_object.endpoint.get(Measure.API_READ, params={**kwargs, **params}).text) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"{str(concerned_object)} not found") log.error("%s while getting measures %s of %s", util.http_error(e), str(metrics_list), str(concerned_object)) raise e @@ -155,8 +155,8 @@ def get_history(concerned_object: object, metrics_list: KeyList, **kwargs) -> li try: data = json.loads(concerned_object.endpoint.get(Measure.API_HISTORY, params={**kwargs, **params}).text) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"{str(concerned_object)} not found") log.error("%s while getting measures %s history of %s", util.http_error(e), str(metrics_list), str(concerned_object)) raise e diff --git a/sonar/organizations.py b/sonar/organizations.py index 6c7b94b07..f14d19319 100644 --- a/sonar/organizations.py +++ b/sonar/organizations.py @@ -24,11 +24,10 @@ """ from __future__ import annotations -from typing import Optional import json from http import HTTPStatus from threading import Lock -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.platform as pf @@ -79,8 +78,8 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Organization: return _OBJECTS[uu] try: data = json.loads(endpoint.get(Organization.SEARCH_API, params={"organizations": key}).text) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key, f"Organization '{key}' not found") log.error("%s getting organization %s", util.http_error(e), key) raise e diff --git a/sonar/permissions/permission_templates.py b/sonar/permissions/permission_templates.py index 0ceda633d..0fb917220 100644 --- a/sonar/permissions/permission_templates.py +++ b/sonar/permissions/permission_templates.py @@ -22,7 +22,7 @@ import json import re -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log from sonar.util import types @@ -141,7 +141,7 @@ def set_as_default(self, what_list: list[str]) -> None: continue try: self.post("permissions/set_default_template", params={"templateId": self.key, "qualifier": qual}) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.error("%s while setting %s as default", utilities.http_error(e), str(self)) raise diff --git a/sonar/permissions/permissions.py b/sonar/permissions/permissions.py index 708c420b6..cc98d0fac 100644 --- a/sonar/permissions/permissions.py +++ b/sonar/permissions/permissions.py @@ -26,7 +26,7 @@ import json from abc import ABC, abstractmethod from http import HTTPStatus -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log from sonar import utilities, errcodes @@ -227,10 +227,10 @@ def _get_api(self, api: str, perm_type: str, ret_field: str, **extra_params) -> params = extra_params.copy() page, nbr_pages = 1, 1 counter = 0 - while page <= nbr_pages: + while page <= nbr_pages and counter <= 5: params["p"] = page - resp = self.endpoint.get(api, params=params) - if resp.ok: + try: + resp = self.endpoint.get(api, params=params) data = json.loads(resp.text) # perms.update({p[ret_field]: p["permissions"] for p in data[perm_type]}) for p in data[perm_type]: @@ -239,12 +239,10 @@ def _get_api(self, api: str, perm_type: str, ret_field: str, **extra_params) -> counter = 0 else: counter += 1 - elif resp.status_code not in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): - # Hack: Different versions of SonarQube return different codes (400 or 404) - utilities.exit_fatal(f"HTTP error {resp.status_code} - Exiting", errcodes.SONAR_API) - page, nbr_pages = page + 1, utilities.nbr_pages(data) - if counter > 5 or not resp.ok: - break + page, nbr_pages = page + 1, utilities.nbr_pages(data) + except (HTTPError, ConnectionError, RequestException) as e: + log.error("%s while retrieving %s permissions", utilities.http_error(e), str(self)) + page += 1 return perms def _post_api(self, api: str, set_field: str, perms_dict: types.JsonPermissions, **extra_params) -> bool: @@ -259,7 +257,7 @@ def _post_api(self, api: str, set_field: str, perms_dict: types.JsonPermissions, params["permission"] = p try: r = self.endpoint.post(api, params=params) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.error("%s while setting permissions %s", utilities.http_error(e), str(self)) result = result and r.ok return result diff --git a/sonar/permissions/quality_permissions.py b/sonar/permissions/quality_permissions.py index 7d1b22b37..a1a52f8f4 100644 --- a/sonar/permissions/quality_permissions.py +++ b/sonar/permissions/quality_permissions.py @@ -24,11 +24,11 @@ from typing import Optional import json -from http import HTTPStatus +from requests import HTTPError, RequestException from sonar.util import types import sonar.logging as log -from sonar import utilities, errcodes +from sonar import utilities from sonar.permissions import permissions MAX_PERMS = 25 @@ -71,16 +71,14 @@ def _get_api(self, api: str, perm_type: tuple[str, ...], ret_field: str, **extra page, nbr_pages = 1, 1 while page <= nbr_pages: params["p"] = page - resp = self.endpoint.get(api, params=params) - if resp.ok: + try: + resp = self.endpoint.get(api, params=params) data = json.loads(resp.text) perms += [p[ret_field] for p in data[perm_type]] - elif resp.status_code not in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): - # Hack: Different versions of SonarQube return different codes (400 or 404) - utilities.exit_fatal(f"HTTP error {resp.status_code} - Exiting", errcodes.SONAR_API) - else: - break - page, nbr_pages = page + 1, utilities.nbr_pages(data) + page, nbr_pages = page + 1, utilities.nbr_pages(data) + except (HTTPError, ConnectionError, RequestException) as e: + log.error("%s while retrieving %s permissions", utilities.http_error(e), str(self)) + page += 1 return perms def _set_perms(self, new_perms: types.ObjectJsonRepr, apis: dict[str, dict[str, str]], field: str, diff_func: callable, **kwargs) -> bool: diff --git a/sonar/platform.py b/sonar/platform.py index ba09bf0db..98e3f8ee8 100644 --- a/sonar/platform.py +++ b/sonar/platform.py @@ -35,7 +35,7 @@ import tempfile import requests import jprops -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException, Timeout import sonar.logging as log import sonar.utilities as util @@ -104,7 +104,7 @@ def __credentials(self) -> tuple[str, str]: def verify_connection(self) -> None: try: self.get("server/version") - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.critical("%s while verifying connection", util.http_error(e)) raise exceptions.ConnectionError(util.sonar_error(e.response)) @@ -254,10 +254,13 @@ def __run_request( lvl = log.DEBUG if r.status_code in mute else log.ERROR log.log(lvl, "%s (%s request)", util.http_error(e), req_type) raise e - except requests.exceptions.Timeout as e: + except Timeout as e: util.exit_fatal(str(e), errcodes.HTTP_TIMEOUT) - except requests.RequestException as e: - util.exit_fatal(str(e), errcodes.SONAR_API) + except (ConnectionError, RequestException) as e: + if exit_on_error: # or (r.status_code not in mute and r.status_code not in _NORMAL_HTTP_ERRORS): + util.exit_fatal(str(e), errcodes.SONAR_API) + log.error(str(e)) + raise return r def global_permissions(self): @@ -282,14 +285,14 @@ def sys_info(self) -> dict[str, any]: try: resp = self.get("system/info", mute=(HTTPStatus.INTERNAL_SERVER_ERROR,)) success = True - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: # Hack: SonarQube randomly returns Error 500 on this API, retry up to 10 times - if e.response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR and counter < 10: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR and counter < 10: log.error("HTTP Error 500 for api/system/info, retrying...") time.sleep(0.5) counter += 1 else: - log.critical("%s while getting system info", util.http_error(e)) + log.error("%s while getting system info", util.http_error(e)) raise e self.__sys_info = json.loads(resp.text) success = True @@ -654,6 +657,7 @@ def _audit_lta_latest(self) -> list[Problem]: v = latest() if not v: return [] + # pylint: disable-next=E0606 return [Problem(rule, self.url, ".".join(sq_vers), ".".join(v))] @@ -808,11 +812,11 @@ def __lta_and_latest() -> tuple[tuple[int, int, int], tuple[int, int, int]]: if len(v) == 2: v.append("0") LATEST = tuple(int(n) for n in v) - log.debug("Sonar update center says LTA (ex-LTS) = %s, LATEST = %s", str(LTA), str(LATEST)) + log.info("Sonar update center says LTA (ex-LTS) = %s, LATEST = %s", str(LTA), str(LATEST)) except (EnvironmentError, HTTPError): LTA = _HARDCODED_LTA LATEST = _HARDCODED_LATEST - log.debug("Sonar update center read failed, hardcoding LTA (ex-LTS) = %s, LATEST = %s", str(LTA), str(LATEST)) + log.info("Sonar update center read failed, hardcoding LTA (ex-LTS) = %s, LATEST = %s", str(LTA), str(LATEST)) try: os.remove(tmpfile) except EnvironmentError: @@ -899,7 +903,7 @@ def basics( return exp -def log_and_exit(exception: requests.exceptions.HTTPError) -> None: +def log_and_exit(exception: Exception) -> None: """If HTTP response is not OK, display an error log and exit""" err_code, msg = util.http_error_and_code(exception) if err_code is None: diff --git a/sonar/portfolio_reference.py b/sonar/portfolio_reference.py index 1e3ad3645..3ab9a2b60 100644 --- a/sonar/portfolio_reference.py +++ b/sonar/portfolio_reference.py @@ -25,7 +25,7 @@ from __future__ import annotations from http import HTTPStatus -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.platform as pf @@ -73,8 +73,8 @@ def create(cls, reference: object, parent: object, params: types.ApiParams = Non try: parent.endpoint.post("views/add_portfolio", params={"portfolio": parent.key, "reference": reference.key}) - except HTTPError as e: - if e.response.status_code == HTTPStatus.BAD_REQUEST: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists log.critical("%s while creating portfolio reference to %s in %s", utilities.http_error(e), str(reference), str(parent)) raise e diff --git a/sonar/portfolios.py b/sonar/portfolios.py index 9c7b25d58..05c0adcb2 100644 --- a/sonar/portfolios.py +++ b/sonar/portfolios.py @@ -30,7 +30,7 @@ import datetime from http import HTTPStatus from threading import Lock -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.platform as pf @@ -262,8 +262,8 @@ def add_reference_subportfolio(self, reference: Portfolio) -> object: self.post("views/add_portfolio", params={"portfolio": self.key, "reference": reference.key}, mute=(HTTPStatus.BAD_REQUEST,)) else: self.post("views/add_local_view", params={"key": self.key, "ref_key": reference.key}, mute=(HTTPStatus.BAD_REQUEST,)) - except HTTPError as e: - if e.response.status_code != HTTPStatus.BAD_REQUEST: + except (HTTPError, ConnectionError, RequestException) as e: + if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: log.error("%s while adding reference subportfolio to %s", util.http_error(e), str(self)) raise self._sub_portfolios.update({reference.key: ref}) @@ -275,8 +275,8 @@ def add_standard_subportfolio(self, key: str, name: str, **kwargs) -> Portfolio: try: if self.endpoint.version() < (9, 3, 0): self.post("views/add_sub_view", params={"key": self.key, "name": name, "subKey": key}, mute=(HTTPStatus.BAD_REQUEST,)) - except HTTPError as e: - if e.response.status_code != HTTPStatus.BAD_REQUEST: + except (HTTPError, ConnectionError, RequestException) as e: + if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: log.error("%s while adding standard subportfolio to %s", util.http_error(e), str(self)) raise self._sub_portfolios.update({subp.key: subp}) @@ -430,11 +430,11 @@ def add_project_branches(self, branch_dict: dict[str, Union[str, object]]) -> Po if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.key, f"Project '{key}' or branch '{branch}' not found, can't be added to {str(self)}") if e.response.status_code == HTTPStatus.BAD_REQUEST: - # Project or branch already in portfolio - pass - else: log.error("%s while adding project branches to %s", util.http_error(e), str(self)) raise + except (ConnectionError, RequestException) as e: + log.error("%s while adding project branches to %s", util.http_error(e), str(self)) + raise return self def set_manual_mode(self) -> Portfolio: @@ -523,11 +523,11 @@ def add_application_branch(self, app_key: str, branch: str = settings.DEFAULT_BR log.info("%s: Adding %s", str(self), str(app_branch)) params = {"key": self.key, "application": app_key, "branch": branch} self.post("views/add_application_branch", params=params, mute=(HTTPStatus.BAD_REQUEST,)) - except HTTPError as e: - if e.response.status_code != HTTPStatus.BAD_REQUEST: + except (HTTPError, ConnectionError, RequestException) as e: + if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: log.error("%s while adding application branch to %s", util.http_error(e), str(self)) raise - log.warning(util.sonar_error(e.response)) + log.warning(util.http_error(e)) if app_key not in self._applications: self._applications[app_key] = [] self._applications[app_key].append(branch) @@ -583,11 +583,8 @@ def get_project_list(self) -> list[str]: data = json.loads(self.get("api/measures/component_tree", params=params).text) nbr_projects = util.nbr_total_elements(data) proj_key_list += [c["refKey"] for c in data["components"]] - except HTTPError as e: - if e.response.status_code in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): - log.warning("%s while collecting projects from %s, stopping collection", util.http_error(e), str(self)) - else: - log.critical("HTTP Error %s while collecting projects from %s, proceeding anyway", str(e), str(self)) + except (HTTPError, ConnectionError, RequestException) as e: + log.error("%s while collecting projects from %s, stopping collection", util.http_error(e), str(self)) break nbr_pages = util.nbr_pages(data) log.debug("Number of projects: %d - Page: %d/%d", nbr_projects, page, nbr_pages) @@ -794,7 +791,7 @@ def export( exported_portfolios[k] = exp else: log.debug("Skipping export of %s, it's a standard sub-portfolio", str(p)) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.error("%s while exporting %s, export will be empty for this portfolio", util.http_error(e), str(p)) exported_portfolios[k] = {} i += 1 diff --git a/sonar/projects.py b/sonar/projects.py index 3f594f541..5dd0db48e 100644 --- a/sonar/projects.py +++ b/sonar/projects.py @@ -34,7 +34,7 @@ from http import HTTPStatus from threading import Thread, Lock from queue import Queue -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.platform as pf @@ -168,8 +168,8 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Project: log.error("Project key '%s' not found", key) raise exceptions.ObjectNotFound(key, f"Project key '{key}' not found") return cls.load(endpoint, data["components"][0]) - except HTTPError as e: - if e.response.status_code != HTTPStatus.FORBIDDEN: + except (HTTPError, ConnectionError, RequestException) as e: + if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.FORBIDDEN: log.error("%s while getting project '%s'", util.http_error(e), key) raise data = json.loads(endpoint.get(_NAV_API, params={"component": key}).text) @@ -208,8 +208,8 @@ def create(cls, endpoint: pf.Platform, key: str, name: str) -> Project: """ try: endpoint.post(_CREATE_API, params={"project": key, "name": name}) - except HTTPError as e: - if e.response.status_code == HTTPStatus.BAD_REQUEST: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(key, e.response.text) log.error("%s while creating project '%s'", util.http_error(e), key) raise @@ -380,8 +380,8 @@ def binding(self): resp = self.get("alm_settings/get_binding", params={"project": self.key}, mute=(HTTPStatus.NOT_FOUND,)) self._binding["has_binding"] = True self._binding["binding"] = json.loads(resp.text) - except HTTPError as e: - if e.response.status_code in (HTTPStatus.NOT_FOUND, HTTPStatus.BAD_REQUEST): + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code in (HTTPStatus.NOT_FOUND, HTTPStatus.BAD_REQUEST): # Hack: 8.9 returns 404, 9.x returns 400 self._binding["has_binding"] = False else: @@ -559,9 +559,9 @@ def __audit_binding_valid(self, audit_settings: types.ConfigSettings) -> list[Pr try: _ = self.get("alm_settings/validate_binding", params={"project": self.key}) log.debug("%s binding is valid", str(self)) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: # Hack: 8.9 returns 404, 9.x returns 400 - if e.response.status_code in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): + if isinstance(e, HTTPError) and e.response.status_code in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): return [Problem(get_rule(RuleId.PROJ_INVALID_BINDING), self, str(self))] log.error("%s while auditing %s binding, skipped", util.http_error(e), str(self)) return [] @@ -619,7 +619,7 @@ def ci(self) -> str: data = json.loads(self.get("project_analyses/search", params={"project": self.key, "ps": 1}).text)["analyses"] if len(data) > 0: self._ci, self._revision = data[0].get("detectedCI", "unknown"), data[0].get("revision", "unknown") - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.warning("%s while getting %s CI tool", util.http_error(e), str(self)) except KeyError: log.warning("KeyError, can't retrieve CI tool and revision") @@ -666,8 +666,8 @@ def audit(self, audit_settings: types.ConfigSettings) -> list[Problem]: problems += self._audit_bg_task(audit_settings) problems += self.__audit_binding_valid(audit_settings) problems += self.__audit_scanner(audit_settings) - except HTTPError as e: - if e.response.status_code == HTTPStatus.FORBIDDEN: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.FORBIDDEN: log.error("Not enough permission to fully audit %s", str(self)) else: log.error("%s while auditing %s", util.http_error(e), str(self)) @@ -690,6 +690,8 @@ def export_zip(self, timeout: int = 180) -> dict[str, str]: resp = self.post("project_dump/export", params={"key": self.key}) except HTTPError as e: return {"status": f"HTTP_ERROR {e.response.status_code}"} + except (ConnectionError, RequestException) as e: + return {"status": str(e)} data = json.loads(resp.text) status = tasks.Task(endpoint=self.endpoint, task_id=data["taskId"], concerned_object=self, data=data).wait_for_completion(timeout=timeout) if status != tasks.SUCCESS: @@ -708,7 +710,7 @@ def export_async(self) -> Union[str, None]: log.info("Exporting %s (asynchronously)", str(self)) try: return json.loads(self.post("project_dump/export", params={"key": self.key}).text)["taskId"] - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.error("%s while exporting zip of %s CI", util.http_error(e), str(self)) return None @@ -1049,19 +1051,13 @@ def export(self, export_settings: types.ConfigSettings, settings_list: dict[str, if not export_settings.get("INCLUDE_INHERITED", False) and s.inherited: continue json_data.update(s.to_json()) - except HTTPError as e: - if e.response.status_code == HTTPStatus.FORBIDDEN: - log.critical("Insufficient privileges to access %s, export of this project interrupted", str(self)) - json_data["error"] = "Insufficient permissions while exporting project, export interrupted" - else: - log.critical("%s while exporting %s, export of this project interrupted", util.http_error(e), str(self)) - json_data["error"] = f"HTTP error {str(e)} while extracting project" - except ConnectionError as e: - log.critical("Connecting error %s while exporting %s, export of this project interrupted", str(e), str(self)) - json_data["error"] = f"Connection error {str(e)} while extracting project, export interrupted" + except (HTTPError, ConnectionError, RequestException) as e: + errmsg = util.http_error(e) + log.error("Exception: %s while exporting %s, export of this project interrupted", errmsg, str(self)) + json_data["error"] = f"{errmsg} while extracting project" except Exception as e: - log.critical("Exception %s while exporting %s, export of this project interrupted", str(e), str(self)) - json_data["error"] = f"Exception {str(e)} while exporting project, export interrupted" + log.critical("Exception: %s while exporting %s, export of this project interrupted", errmsg, str(self)) + json_data["error"] = f"{errmsg} while extracting project" log.debug("Exporting %s done", str(self)) return util.remove_nones(json_data) @@ -1094,11 +1090,10 @@ def set_permissions(self, desired_permissions: types.ObjectJsonRepr) -> bool: try: self.permissions().set(desired_permissions) return True - except HTTPError as e: - if e.response.status_code != HTTPStatus.BAD_REQUEST: - log.error("%s while setting permissions of %s", util.http_error(e), str(self)) + except (HTTPError, ConnectionError, RequestException) as e: + log.error("%s while setting permissions of %s", util.http_error(e), str(self)) + if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: raise e - log.error(util.sonar_error(e.response)) return False def set_links(self, desired_links: types.ObjectJsonRepr) -> bool: @@ -1433,11 +1428,8 @@ def __audit_thread(queue: Queue[Project], results: list[Problem], audit_settings results.append(Problem(get_rule(RuleId.PROJ_DUPLICATE_BINDING), project, str(project), str(bindings[bindkey]))) else: bindings[bindkey] = project - except HTTPError as e: - if e.response.status_code == HTTPStatus.FORBIDDEN: - log.error("Not enough permission to fully audit %s", str(project)) - else: - log.error("%s while auditing %s", util.http_error(e), str(project)) + except (HTTPError, ConnectionError, RequestException) as e: + log.error("%s while auditing %s", util.http_error(e), str(project)) queue.task_done() log.debug("%s audit complete", str(project)) log.debug("Queue empty, exiting thread") @@ -1493,6 +1485,7 @@ def __export_thread(queue: Queue[Project], results: dict[str, str], export_setti lvl = log.INFO if nb % 10 == 0 or tot - nb < 10 else log.DEBUG log.log(lvl, "%d/%d projects exported (%d%%)", nb, tot, (nb * 100) // tot) queue.task_done() + log.info("Project export queue empty, export complete") def export( diff --git a/sonar/qualitygates.py b/sonar/qualitygates.py index 9b3f64e4d..30e5aadce 100644 --- a/sonar/qualitygates.py +++ b/sonar/qualitygates.py @@ -29,7 +29,7 @@ from http import HTTPStatus import json -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.sqobject as sq @@ -173,8 +173,8 @@ def projects(self) -> dict[str, projects.Project]: params["p"] = page try: resp = self.get(APIS["get_projects"], params=params) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.name, f"{str(self)} not found") log.error("%s while getting %s projects", util.http_error(e), str(self)) raise diff --git a/sonar/qualityprofiles.py b/sonar/qualityprofiles.py index 6df52ea11..165807dd3 100644 --- a/sonar/qualityprofiles.py +++ b/sonar/qualityprofiles.py @@ -26,7 +26,7 @@ from http import HTTPStatus from queue import Queue from threading import Thread, Lock -from requests import HTTPError +from requests import HTTPError, RequestException import requests.utils import sonar.logging as log @@ -260,11 +260,11 @@ def activate_rule(self, rule_key: str, severity: str = None, **params) -> bool: api_params = {"key": self.key, "rule": rule_key, "severity": severity} if len(params) > 0: api_params["params"] = ";".join([f"{k}={v}" for k, v in params.items()]) - r = self.post("qualityprofiles/activate_rule", params=api_params) - if r.status_code == HTTPStatus.NOT_FOUND: - log.error("Rule %s not found, can't activate it in %s", rule_key, str(self)) - elif r.status_code == HTTPStatus.BAD_REQUEST: - log.error("HTTP error %d while trying to activate rule %s in %s", r.status_code, rule_key, str(self)) + try: + r = self.post("qualityprofiles/activate_rule", params=api_params) + except (HTTPError, ConnectionError, RequestException) as e: + log.error("%s while trying to activate rule %s in %s", util.http_error(e), rule_key, str(self)) + return False return r.ok def activate_rules(self, ruleset: dict[str, str]) -> bool: @@ -283,7 +283,7 @@ def activate_rules(self, ruleset: dict[str, str]) -> bool: ok = ok and self.activate_rule(rule_key=r_key, severity=sev, **r_data["params"]) else: ok = ok and self.activate_rule(rule_key=r_key, severity=sev) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: ok = False log.error("%s while activating rules in '%s'", util.http_error(e), r_key) return ok diff --git a/sonar/rules.py b/sonar/rules.py index fde05d316..1e63dc4f3 100644 --- a/sonar/rules.py +++ b/sonar/rules.py @@ -27,7 +27,7 @@ import json from typing import Optional from http import HTTPStatus -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.sqobject as sq @@ -131,8 +131,8 @@ def get_object(cls, endpoint: platform.Platform, key: str) -> Rule: log.debug("Reading rule key '%s'", key) try: r = endpoint.get(_DETAILS_API, params={"key": key}) - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key=key, message=f"Rule key '{key}' does not exist") log.error("%s while getting rule'%s'", utilities.http_error(e), key) return Rule(endpoint=endpoint, key=key, data=json.loads(r.text)["rule"]) diff --git a/sonar/settings.py b/sonar/settings.py index ed82c491a..0a46d4970 100644 --- a/sonar/settings.py +++ b/sonar/settings.py @@ -26,7 +26,7 @@ import json from typing import Union from http import HTTPStatus -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log import sonar.platform as pf @@ -454,11 +454,11 @@ def set_new_code_period(endpoint: pf.Platform, nc_type: str, nc_value: str, proj ok = ok and endpoint.post(API_SET, params={"key": "sonar.leak.period", "value": nc_value, "project": project_key}).ok else: ok = endpoint.post(API_NEW_CODE_SET, params={"type": nc_type, "value": nc_value, "project": project_key, "branch": branch}).ok - except HTTPError as e: - if e.response.status_code == HTTPStatus.BAD_REQUEST: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.UnsupportedOperation(f"Can't set project new code period: {e.response.text}") log.error("%s setting new code period of '%s'", util.http_error(e), str(project_key)) - raise + return False return ok @@ -487,11 +487,11 @@ def set_visibility(endpoint: pf.Platform, visibility: str, component: object = N else: log.debug("Setting setting '%s' to value '%s'", PROJECT_DEFAULT_VISIBILITY, str(visibility)) return endpoint.post("projects/update_default_visibility", params={"projectVisibility": visibility}).ok - except HTTPError as e: - if e.response.status_code == HTTPStatus.BAD_REQUEST: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.UnsupportedOperation(f"Can't set project default visibility: {e.response.text}") log.error("%s setting new code period of '%s'", util.http_error(e), str(component)) - raise + return False def set_setting(endpoint: pf.Platform, key: str, value: any, component: object = None) -> bool: @@ -503,7 +503,7 @@ def set_setting(endpoint: pf.Platform, key: str, value: any, component: object = else: try: s.set(value) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.error("%s while setting setting '%s'", util.http_error(e), key, str(component)) return False except exceptions.UnsupportedOperation as e: diff --git a/sonar/sqobject.py b/sonar/sqobject.py index 977841427..07a5a4557 100644 --- a/sonar/sqobject.py +++ b/sonar/sqobject.py @@ -29,7 +29,7 @@ from queue import Queue from threading import Thread import requests -from requests.exceptions import HTTPError +from requests import HTTPError, RequestException import sonar.logging as log from sonar.util import types @@ -116,7 +116,7 @@ def __search_thread(queue: Queue) -> None: objects[obj[key_field]] = object_class.load(endpoint=endpoint, data=obj) else: objects[obj[key_field]] = object_class(endpoint, obj[key_field], data=obj) - except HTTPError as e: + except (HTTPError, ConnectionError, RequestException) as e: log.critical("%s while searching %s, search skipped", utilities.http_error(e), object_class.__name__) queue.task_done() @@ -163,8 +163,8 @@ def delete_object(object: SqObject, api: str, params: types.ApiParams, map: dict map.pop(object.uuid(), None) log.info("Successfully deleted %s", str(object)) return r.ok - except HTTPError as e: - if e.response.status_code == HTTPStatus.NOT_FOUND: + except (HTTPError, ConnectionError, RequestException) as e: + if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: map.pop(object.uuid(), None) raise exceptions.ObjectNotFound(object.key, f"{str(object)} not found for delete") log.error("%s while deleting object '%s'", utilities.http_error(e), str(object)) diff --git a/sonar/utilities.py b/sonar/utilities.py index 309727188..eb3f4245c 100644 --- a/sonar/utilities.py +++ b/sonar/utilities.py @@ -52,7 +52,7 @@ def check_last_version(package_url: str) -> None: try: r = requests.get(url=package_url, headers={"Accept": "application/vnd.pypi.simple.v1+json"}, timeout=10) r.raise_for_status() - except (requests.RequestException, requests.exceptions.HTTPError, requests.exceptions.Timeout) as e: + except (requests.RequestException, requests.HTTPError, requests.Timeout) as e: log.info("Can't access pypi.org, error %s", str(e)) return txt_version = json.loads(r.text)["versions"][-1] @@ -423,11 +423,11 @@ def sonar_error(response: requests.models.Response) -> str: return "" -def http_error_and_code(exception: requests.exceptions.HTTPError) -> tuple[int, str]: +def http_error_and_code(exception: requests.HTTPError) -> tuple[int, str]: """Returns the Sonar error code of an API HTTP response, or None if no error""" response = exception.response if response.ok: - return None, None + return None, "No error" tool_msg = f"For request URL {response.request.url}\n" code = response.status_code if code == HTTPStatus.UNAUTHORIZED: @@ -442,10 +442,13 @@ def http_error_and_code(exception: requests.exceptions.HTTPError) -> tuple[int, return err_code, f"{tool_msg}: {sonar_error(response)}" -def http_error(exception: requests.exceptions.HTTPError) -> tuple[int, str]: - """Returns the Sonar error code of an API HTTP response, or None if no error""" - _, errmsg = http_error_and_code(exception) - return errmsg +def http_error(exception: Exception) -> str: + """Returns the error of an Sonar API HTTP response, or None if no error""" + if isinstance(exception, requests.HTTPError): + _, errmsg = http_error_and_code(exception) + return errmsg + else: + return str(exception) def object_key(key_or_obj): From ed68231feab2088ad7a51446cb1965244c7aa343 Mon Sep 17 00:00:00 2001 From: Olivier Korach Date: Sat, 12 Oct 2024 16:06:46 +0200 Subject: [PATCH 4/8] Change http_error in error_msg --- cli/findings_export.py | 8 ++++---- cli/loc.py | 4 ++-- cli/measures_export.py | 2 +- sonar/app_branches.py | 4 ++-- sonar/applications.py | 8 ++++---- sonar/branches.py | 12 ++++++------ sonar/devops.py | 2 +- sonar/hotspots.py | 2 +- sonar/issues.py | 4 ++-- sonar/measures.py | 4 ++-- sonar/organizations.py | 2 +- sonar/permissions/permission_templates.py | 2 +- sonar/permissions/permissions.py | 4 ++-- sonar/permissions/quality_permissions.py | 2 +- sonar/platform.py | 6 +++--- sonar/portfolio_reference.py | 2 +- sonar/portfolios.py | 16 ++++++++-------- sonar/projects.py | 20 ++++++++++---------- sonar/qualitygates.py | 2 +- sonar/qualityprofiles.py | 4 ++-- sonar/rules.py | 2 +- sonar/settings.py | 6 +++--- sonar/sqobject.py | 4 ++-- sonar/utilities.py | 2 +- 24 files changed, 62 insertions(+), 62 deletions(-) diff --git a/cli/findings_export.py b/cli/findings_export.py index 6890944a3..900eafbb0 100755 --- a/cli/findings_export.py +++ b/cli/findings_export.py @@ -295,7 +295,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ component.endpoint, component.key, branch=params.get("branch", None), pull_request=params.get("pullRequest", None) ) except (HTTPError, ConnectionError, RequestException) as e: - log.critical("%s while exporting findings of %s, skipped", util.http_error(e), str(component)) + log.critical("%s while exporting findings of %s, skipped", util.error_msg(e), str(component)) findings_list = {} write_queue.put([findings_list, False]) else: @@ -324,7 +324,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ try: findings_list = component.get_issues(filters=new_params) except (HTTPError, ConnectionError, RequestException) as e: - log.critical("%s while exporting issues of %s, skipped", util.http_error(e), str(component)) + log.critical("%s while exporting issues of %s, skipped", util.error_msg(e), str(component)) findings_list = {} else: log.debug("Status = %s, Types = %s, Resol = %s, Sev = %s", str(i_statuses), str(i_types), str(i_resols), str(i_sevs)) @@ -334,7 +334,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ try: findings_list.update(component.get_hotspots(filters=new_params)) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while exporting hotspots of object key %s, skipped", util.http_error(e), str(component)) + log.error("%s while exporting hotspots of object key %s, skipped", util.error_msg(e), str(component)) else: log.debug("Status = %s, Types = %s, Resol = %s, Sev = %s", str(h_statuses), str(h_types), str(h_resols), str(h_sevs)) log.info("Selected types, severities, resolutions or statuses disables issue search") @@ -352,7 +352,7 @@ def store_findings(components_list: dict[str, object], params: ConfigSettings) - log.debug("Queue %s task %s put", str(my_queue), str(comp)) my_queue.put((comp, params.copy())) except (HTTPError, ConnectionError, RequestException) as e: - log.critical("%s while exporting findings of %s, skipped", util.http_error(e), str(comp)) + log.critical("%s while exporting findings of %s, skipped", util.error_msg(e), str(comp)) threads = params.get(options.NBR_THREADS, 4) for i in range(min(threads, len(components_list))): diff --git a/cli/loc.py b/cli/loc.py index 8217b984b..e0bf1ca00 100644 --- a/cli/loc.py +++ b/cli/loc.py @@ -52,7 +52,7 @@ def __get_csv_row(o: object, **kwargs) -> tuple[list[str], str]: try: loc = o.loc() except (HTTPError, ConnectionError, RequestException) as e: - log.warning("%s, LoC export of %s skipped", util.http_error(e), str(o)) + log.warning("%s, LoC export of %s skipped", util.error_msg(e), str(o)) loc = "" arr = [o.key, loc] obj_type = type(o).__name__.lower() @@ -114,7 +114,7 @@ def __get_object_json_data(o: object, **kwargs) -> dict[str, str]: try: d["ncloc"] = o.loc() except (HTTPError, ConnectionError, RequestException) as e: - log.warning("%s, LoC export of %s skipped", util.http_error(e), str(o)) + log.warning("%s, LoC export of %s skipped", util.error_msg(e), str(o)) if kwargs[options.WITH_NAME]: d[f"{parent_type}Name"] = o.name if obj_type in ("branch", "applicationbranch"): diff --git a/cli/measures_export.py b/cli/measures_export.py index 538a996a4..d791781cc 100755 --- a/cli/measures_export.py +++ b/cli/measures_export.py @@ -283,7 +283,7 @@ def __get_measures(obj: object, wanted_metrics: types.KeyList, hist: bool) -> Un else: data.update(__get_object_measures(obj, wanted_metrics)) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s, measures export skipped for %s", util.http_error(e), str(obj)) + log.error("%s, measures export skipped for %s", util.error_msg(e), str(obj)) return None return data diff --git a/sonar/app_branches.py b/sonar/app_branches.py index 1dabc8fa2..6197b5757 100644 --- a/sonar/app_branches.py +++ b/sonar/app_branches.py @@ -112,7 +112,7 @@ def create(cls, app: App, name: str, project_branches: list[Branch]) -> Applicat except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(f"app.App {app.key} branch '{name}", e.response.text) - log.critical("%s while creating branch '%s' of '%s'", utilities.http_error(e), name, str(app)) + log.critical("%s while creating branch '%s' of '%s'", utilities.error_msg(e), name, str(app)) raise return ApplicationBranch(app=app, name=name, project_branches=project_branches) @@ -187,7 +187,7 @@ def update(self, name: str, project_branches: list[Branch]) -> bool: except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(str(self), e.response.text) - log.error("%s while updating '%s'", utilities.http_error(e), str(self)) + log.error("%s while updating '%s'", utilities.error_msg(e), str(self)) raise self.name = name diff --git a/sonar/applications.py b/sonar/applications.py index 2995df152..5204fadcc 100644 --- a/sonar/applications.py +++ b/sonar/applications.py @@ -93,7 +93,7 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Application: except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key, f"Application key '{key}' not found") - log.error("%s while getting app key '%s'", util.http_error(e), key) + log.error("%s while getting app key '%s'", util.error_msg(e), key) raise return cls.load(endpoint, data) @@ -136,7 +136,7 @@ def create(cls, endpoint: pf.Platform, key: str, name: str) -> Application: except (HTTPError, ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(key, e.response.text) - log.critical("%s while creating app key '%s'", util.http_error(e), key) + log.critical("%s while creating app key '%s'", util.error_msg(e), key) raise return Application(endpoint, key, name) @@ -154,7 +154,7 @@ def refresh(self) -> None: if e.response.status_code == HTTPStatus.NOT_FOUND: _OBJECTS.pop(self.uuid(), None) raise exceptions.ObjectNotFound(self.key, f"{str(self)} not found") - log.error("%s while refreshing %s", util.http_error(e), str(self)) + log.error("%s while refreshing %s", util.error_msg(e), str(self)) raise def __str__(self) -> str: @@ -393,7 +393,7 @@ def add_projects(self, project_list: list[str]) -> bool: log.warning("Project '%s' not found, can't be added to %s", proj, self) ok = False else: - log.error("%s while adding projects to %s", util.http_error(e), str(self)) + log.error("%s while adding projects to %s", util.error_msg(e), str(self)) raise return ok diff --git a/sonar/branches.py b/sonar/branches.py index c8b27f9e9..c53ef38bf 100644 --- a/sonar/branches.py +++ b/sonar/branches.py @@ -92,7 +92,7 @@ def get_object(cls, concerned_object: projects.Project, branch_name: str) -> Bra except (HTTPError, ConnectionError, RequestException) as e: if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"Project '{concerned_object.key}' not found") - log.critical("%s while getting branch '%s' of %s", util.http_error(e), branch_name, str(concerned_object)) + log.critical("%s while getting branch '%s' of %s", util.error_msg(e), branch_name, str(concerned_object)) raise for br in data.get("branches", []): if br["name"] == branch_name: @@ -132,7 +132,7 @@ def refresh(self) -> Branch: except (HTTPError, ConnectionError, RequestException) as e: if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.key, f"{str(self)} not found in SonarQube") - log.error("%s while refreshing %s", util.http_error(e), str(self)) + log.error("%s while refreshing %s", util.error_msg(e), str(self)) for br in data.get("branches", []): if br["name"] == self.name: self._load(br) @@ -189,7 +189,7 @@ def delete(self) -> bool: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: log.warning("Can't delete %s, it's the main branch", str(self)) else: - log.error("%s while deleting %s", util.http_error(e), str(self)) + log.error("%s while deleting %s", util.error_msg(e), str(self)) return False def new_code(self) -> str: @@ -205,7 +205,7 @@ def new_code(self) -> str: except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.concerned_object.key, f"{str(self.concerned_object)} not found") - log.error("%s while getting new code period of %s", util.http_error(e), str(self)) + log.error("%s while getting new code period of %s", util.error_msg(e), str(self)) raise e for b in data["newCodePeriods"]: new_code = settings.new_code_to_string(b) @@ -268,7 +268,7 @@ def rename(self, new_name): except (HTTPError, ConnectionError, RequestException) as e: if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.concerned_object.key, f"str{self.concerned_object} not found") - log.error("%s while renaming %s", util.http_error(e), str(self)) + log.error("%s while renaming %s", util.error_msg(e), str(self)) raise _OBJECTS.pop(self.uuid(), None) self.name = new_name @@ -365,7 +365,7 @@ def audit(self, audit_settings: types.ConfigSettings) -> list[Problem]: try: return self.__audit_last_analysis(audit_settings) + self.__audit_zero_loc() + self.__audit_never_analyzed() except (HTTPError, RequestException, Exception) as e: - log.error("%s while auditing %s, audit skipped", util.http_error(e), str(self)) + log.error("%s while auditing %s, audit skipped", util.error_msg(e), str(self)) else: log.debug("Branch audit disabled, skipping audit of %s", str(self)) return [] diff --git a/sonar/devops.py b/sonar/devops.py index feeeebb1d..df8bac5c8 100644 --- a/sonar/devops.py +++ b/sonar/devops.py @@ -113,7 +113,7 @@ def create(cls, endpoint: platform.Platform, key: str, plt_type: str, url_or_wor if e.response.status_code == HTTPStatus.BAD_REQUEST and endpoint.edition() in ("community", "developer"): log.warning("Can't set DevOps platform '%s', don't you have more that 1 of that type?", key) raise exceptions.UnsupportedOperation(f"Can't set DevOps platform '{key}', don't you have more that 1 of that type?") - log.error("%s while creating devops platform %s/%s/%s", util.http_error(e), key, plt_type, url_or_workspace) + log.error("%s while creating devops platform %s/%s/%s", util.error_msg(e), key, plt_type, url_or_workspace) raise o = DevopsPlatform(endpoint=endpoint, key=key, platform_type=plt_type) o.refresh() diff --git a/sonar/hotspots.py b/sonar/hotspots.py index d02004d29..75392d4eb 100644 --- a/sonar/hotspots.py +++ b/sonar/hotspots.py @@ -407,7 +407,7 @@ def search(endpoint: pf.Platform, filters: types.ApiParams = None) -> dict[str, log.warning("No hotspots found with search params %s", str(inline_filters)) nbr_hotspots = 0 return {} - log.error("%s while searching hotspots", util.http_error(e)) + log.error("%s while searching hotspots", util.error_msg(e)) break nbr_pages = util.nbr_pages(data) log.debug("Number of hotspots: %d - Page: %d/%d", nbr_hotspots, inline_filters["p"], nbr_pages) diff --git a/sonar/issues.py b/sonar/issues.py index 79ee42c4e..d13975d32 100644 --- a/sonar/issues.py +++ b/sonar/issues.py @@ -733,7 +733,7 @@ def __search_thread(queue: Queue) -> None: issue_list[i["key"]] = get_object(endpoint=endpoint, key=i["key"], data=i) log.debug("Added %d issues in threaded search page %d", len(data["issues"]), page) except (HTTPError, ConnectionError, RequestException, Exception) as e: - log.error("%s while searching issues, search may be incomplete", util.http_error(e)) + log.error("%s while searching issues, search may be incomplete", util.error_msg(e)) queue.task_done() @@ -859,7 +859,7 @@ def count_by_rule(endpoint: pf.Platform, **kwargs) -> dict[str, int]: rulecount[d["val"]] = 0 rulecount[d["val"]] += d["count"] except (HTTPError, Exception, RequestException) as e: - log.error("%s while counting issues per rule, count may be incomplete", util.http_error(e)) + log.error("%s while counting issues per rule, count may be incomplete", util.error_msg(e)) return rulecount diff --git a/sonar/measures.py b/sonar/measures.py index 714225b0e..a41fa3ff2 100644 --- a/sonar/measures.py +++ b/sonar/measures.py @@ -127,7 +127,7 @@ def get(concerned_object: object, metrics_list: KeyList, **kwargs) -> dict[str, except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"{str(concerned_object)} not found") - log.error("%s while getting measures %s of %s", util.http_error(e), str(metrics_list), str(concerned_object)) + log.error("%s while getting measures %s of %s", util.error_msg(e), str(metrics_list), str(concerned_object)) raise e m_dict = {m: None for m in metrics_list} for m in data["component"]["measures"]: @@ -158,7 +158,7 @@ def get_history(concerned_object: object, metrics_list: KeyList, **kwargs) -> li except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"{str(concerned_object)} not found") - log.error("%s while getting measures %s history of %s", util.http_error(e), str(metrics_list), str(concerned_object)) + log.error("%s while getting measures %s history of %s", util.error_msg(e), str(metrics_list), str(concerned_object)) raise e res_list = [] # last_metric, last_date = "", "" diff --git a/sonar/organizations.py b/sonar/organizations.py index f14d19319..8fb3fdc9d 100644 --- a/sonar/organizations.py +++ b/sonar/organizations.py @@ -81,7 +81,7 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Organization: except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key, f"Organization '{key}' not found") - log.error("%s getting organization %s", util.http_error(e), key) + log.error("%s getting organization %s", util.error_msg(e), key) raise e if len(data["organizations"]) == 0: raise exceptions.ObjectNotFound(key, f"Organization '{key}' not found") diff --git a/sonar/permissions/permission_templates.py b/sonar/permissions/permission_templates.py index 0fb917220..db2a4545e 100644 --- a/sonar/permissions/permission_templates.py +++ b/sonar/permissions/permission_templates.py @@ -142,7 +142,7 @@ def set_as_default(self, what_list: list[str]) -> None: try: self.post("permissions/set_default_template", params={"templateId": self.key, "qualifier": qual}) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while setting %s as default", utilities.http_error(e), str(self)) + log.error("%s while setting %s as default", utilities.error_msg(e), str(self)) raise def set_pattern(self, pattern: str) -> PermissionTemplate: diff --git a/sonar/permissions/permissions.py b/sonar/permissions/permissions.py index cc98d0fac..c9b189ec3 100644 --- a/sonar/permissions/permissions.py +++ b/sonar/permissions/permissions.py @@ -241,7 +241,7 @@ def _get_api(self, api: str, perm_type: str, ret_field: str, **extra_params) -> counter += 1 page, nbr_pages = page + 1, utilities.nbr_pages(data) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while retrieving %s permissions", utilities.http_error(e), str(self)) + log.error("%s while retrieving %s permissions", utilities.error_msg(e), str(self)) page += 1 return perms @@ -258,7 +258,7 @@ def _post_api(self, api: str, set_field: str, perms_dict: types.JsonPermissions, try: r = self.endpoint.post(api, params=params) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while setting permissions %s", utilities.http_error(e), str(self)) + log.error("%s while setting permissions %s", utilities.error_msg(e), str(self)) result = result and r.ok return result diff --git a/sonar/permissions/quality_permissions.py b/sonar/permissions/quality_permissions.py index a1a52f8f4..13de9dd38 100644 --- a/sonar/permissions/quality_permissions.py +++ b/sonar/permissions/quality_permissions.py @@ -77,7 +77,7 @@ def _get_api(self, api: str, perm_type: tuple[str, ...], ret_field: str, **extra perms += [p[ret_field] for p in data[perm_type]] page, nbr_pages = page + 1, utilities.nbr_pages(data) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while retrieving %s permissions", utilities.http_error(e), str(self)) + log.error("%s while retrieving %s permissions", utilities.error_msg(e), str(self)) page += 1 return perms diff --git a/sonar/platform.py b/sonar/platform.py index 98e3f8ee8..a6e1a06e3 100644 --- a/sonar/platform.py +++ b/sonar/platform.py @@ -105,7 +105,7 @@ def verify_connection(self) -> None: try: self.get("server/version") except (HTTPError, ConnectionError, RequestException) as e: - log.critical("%s while verifying connection", util.http_error(e)) + log.critical("%s while verifying connection", util.error_msg(e)) raise exceptions.ConnectionError(util.sonar_error(e.response)) def version(self) -> tuple[int, int, int]: @@ -252,7 +252,7 @@ def __run_request( log_and_exit(e) else: lvl = log.DEBUG if r.status_code in mute else log.ERROR - log.log(lvl, "%s (%s request)", util.http_error(e), req_type) + log.log(lvl, "%s (%s request)", util.error_msg(e), req_type) raise e except Timeout as e: util.exit_fatal(str(e), errcodes.HTTP_TIMEOUT) @@ -292,7 +292,7 @@ def sys_info(self) -> dict[str, any]: time.sleep(0.5) counter += 1 else: - log.error("%s while getting system info", util.http_error(e)) + log.error("%s while getting system info", util.error_msg(e)) raise e self.__sys_info = json.loads(resp.text) success = True diff --git a/sonar/portfolio_reference.py b/sonar/portfolio_reference.py index 3ab9a2b60..87efd1030 100644 --- a/sonar/portfolio_reference.py +++ b/sonar/portfolio_reference.py @@ -76,7 +76,7 @@ def create(cls, reference: object, parent: object, params: types.ApiParams = Non except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists - log.critical("%s while creating portfolio reference to %s in %s", utilities.http_error(e), str(reference), str(parent)) + log.critical("%s while creating portfolio reference to %s in %s", utilities.error_msg(e), str(reference), str(parent)) raise e return PortfolioReference(reference=reference, parent=parent) diff --git a/sonar/portfolios.py b/sonar/portfolios.py index 05c0adcb2..d4a4168ca 100644 --- a/sonar/portfolios.py +++ b/sonar/portfolios.py @@ -264,7 +264,7 @@ def add_reference_subportfolio(self, reference: Portfolio) -> object: self.post("views/add_local_view", params={"key": self.key, "ref_key": reference.key}, mute=(HTTPStatus.BAD_REQUEST,)) except (HTTPError, ConnectionError, RequestException) as e: if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: - log.error("%s while adding reference subportfolio to %s", util.http_error(e), str(self)) + log.error("%s while adding reference subportfolio to %s", util.error_msg(e), str(self)) raise self._sub_portfolios.update({reference.key: ref}) return ref @@ -277,7 +277,7 @@ def add_standard_subportfolio(self, key: str, name: str, **kwargs) -> Portfolio: self.post("views/add_sub_view", params={"key": self.key, "name": name, "subKey": key}, mute=(HTTPStatus.BAD_REQUEST,)) except (HTTPError, ConnectionError, RequestException) as e: if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: - log.error("%s while adding standard subportfolio to %s", util.http_error(e), str(self)) + log.error("%s while adding standard subportfolio to %s", util.error_msg(e), str(self)) raise self._sub_portfolios.update({subp.key: subp}) return subp @@ -430,10 +430,10 @@ def add_project_branches(self, branch_dict: dict[str, Union[str, object]]) -> Po if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.key, f"Project '{key}' or branch '{branch}' not found, can't be added to {str(self)}") if e.response.status_code == HTTPStatus.BAD_REQUEST: - log.error("%s while adding project branches to %s", util.http_error(e), str(self)) + log.error("%s while adding project branches to %s", util.error_msg(e), str(self)) raise except (ConnectionError, RequestException) as e: - log.error("%s while adding project branches to %s", util.http_error(e), str(self)) + log.error("%s while adding project branches to %s", util.error_msg(e), str(self)) raise return self @@ -525,9 +525,9 @@ def add_application_branch(self, app_key: str, branch: str = settings.DEFAULT_BR self.post("views/add_application_branch", params=params, mute=(HTTPStatus.BAD_REQUEST,)) except (HTTPError, ConnectionError, RequestException) as e: if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: - log.error("%s while adding application branch to %s", util.http_error(e), str(self)) + log.error("%s while adding application branch to %s", util.error_msg(e), str(self)) raise - log.warning(util.http_error(e)) + log.warning(util.error_msg(e)) if app_key not in self._applications: self._applications[app_key] = [] self._applications[app_key].append(branch) @@ -584,7 +584,7 @@ def get_project_list(self) -> list[str]: nbr_projects = util.nbr_total_elements(data) proj_key_list += [c["refKey"] for c in data["components"]] except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while collecting projects from %s, stopping collection", util.http_error(e), str(self)) + log.error("%s while collecting projects from %s, stopping collection", util.error_msg(e), str(self)) break nbr_pages = util.nbr_pages(data) log.debug("Number of projects: %d - Page: %d/%d", nbr_projects, page, nbr_pages) @@ -792,7 +792,7 @@ def export( else: log.debug("Skipping export of %s, it's a standard sub-portfolio", str(p)) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while exporting %s, export will be empty for this portfolio", util.http_error(e), str(p)) + log.error("%s while exporting %s, export will be empty for this portfolio", util.error_msg(e), str(p)) exported_portfolios[k] = {} i += 1 if i % 10 == 0 or i == nb_portfolios: diff --git a/sonar/projects.py b/sonar/projects.py index 5dd0db48e..1a06f25da 100644 --- a/sonar/projects.py +++ b/sonar/projects.py @@ -170,7 +170,7 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Project: return cls.load(endpoint, data["components"][0]) except (HTTPError, ConnectionError, RequestException) as e: if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.FORBIDDEN: - log.error("%s while getting project '%s'", util.http_error(e), key) + log.error("%s while getting project '%s'", util.error_msg(e), key) raise data = json.loads(endpoint.get(_NAV_API, params={"component": key}).text) if "errors" in data: @@ -211,7 +211,7 @@ def create(cls, endpoint: pf.Platform, key: str, name: str) -> Project: except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(key, e.response.text) - log.error("%s while creating project '%s'", util.http_error(e), key) + log.error("%s while creating project '%s'", util.error_msg(e), key) raise o = cls(endpoint, key) o.name = name @@ -385,7 +385,7 @@ def binding(self): # Hack: 8.9 returns 404, 9.x returns 400 self._binding["has_binding"] = False else: - log.error("%s while getting '%s' bindinfs", util.http_error(e), str(self)) + log.error("%s while getting '%s' bindinfs", util.error_msg(e), str(self)) raise e log.debug("Binding = %s", util.json_dump(self._binding["binding"])) return self._binding["binding"] @@ -563,7 +563,7 @@ def __audit_binding_valid(self, audit_settings: types.ConfigSettings) -> list[Pr # Hack: 8.9 returns 404, 9.x returns 400 if isinstance(e, HTTPError) and e.response.status_code in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): return [Problem(get_rule(RuleId.PROJ_INVALID_BINDING), self, str(self))] - log.error("%s while auditing %s binding, skipped", util.http_error(e), str(self)) + log.error("%s while auditing %s binding, skipped", util.error_msg(e), str(self)) return [] def get_type(self) -> str: @@ -620,7 +620,7 @@ def ci(self) -> str: if len(data) > 0: self._ci, self._revision = data[0].get("detectedCI", "unknown"), data[0].get("revision", "unknown") except (HTTPError, ConnectionError, RequestException) as e: - log.warning("%s while getting %s CI tool", util.http_error(e), str(self)) + log.warning("%s while getting %s CI tool", util.error_msg(e), str(self)) except KeyError: log.warning("KeyError, can't retrieve CI tool and revision") return self._ci @@ -670,7 +670,7 @@ def audit(self, audit_settings: types.ConfigSettings) -> list[Problem]: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.FORBIDDEN: log.error("Not enough permission to fully audit %s", str(self)) else: - log.error("%s while auditing %s", util.http_error(e), str(self)) + log.error("%s while auditing %s", util.error_msg(e), str(self)) return problems def export_zip(self, timeout: int = 180) -> dict[str, str]: @@ -711,7 +711,7 @@ def export_async(self) -> Union[str, None]: try: return json.loads(self.post("project_dump/export", params={"key": self.key}).text)["taskId"] except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while exporting zip of %s CI", util.http_error(e), str(self)) + log.error("%s while exporting zip of %s CI", util.error_msg(e), str(self)) return None def import_zip(self) -> bool: @@ -1052,7 +1052,7 @@ def export(self, export_settings: types.ConfigSettings, settings_list: dict[str, continue json_data.update(s.to_json()) except (HTTPError, ConnectionError, RequestException) as e: - errmsg = util.http_error(e) + errmsg = util.error_msg(e) log.error("Exception: %s while exporting %s, export of this project interrupted", errmsg, str(self)) json_data["error"] = f"{errmsg} while extracting project" except Exception as e: @@ -1091,7 +1091,7 @@ def set_permissions(self, desired_permissions: types.ObjectJsonRepr) -> bool: self.permissions().set(desired_permissions) return True except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while setting permissions of %s", util.http_error(e), str(self)) + log.error("%s while setting permissions of %s", util.error_msg(e), str(self)) if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: raise e return False @@ -1429,7 +1429,7 @@ def __audit_thread(queue: Queue[Project], results: list[Problem], audit_settings else: bindings[bindkey] = project except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while auditing %s", util.http_error(e), str(project)) + log.error("%s while auditing %s", util.error_msg(e), str(project)) queue.task_done() log.debug("%s audit complete", str(project)) log.debug("Queue empty, exiting thread") diff --git a/sonar/qualitygates.py b/sonar/qualitygates.py index 30e5aadce..365595683 100644 --- a/sonar/qualitygates.py +++ b/sonar/qualitygates.py @@ -176,7 +176,7 @@ def projects(self) -> dict[str, projects.Project]: except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.name, f"{str(self)} not found") - log.error("%s while getting %s projects", util.http_error(e), str(self)) + log.error("%s while getting %s projects", util.error_msg(e), str(self)) raise data = json.loads(resp.text) for prj in data["results"]: diff --git a/sonar/qualityprofiles.py b/sonar/qualityprofiles.py index 165807dd3..c1342962d 100644 --- a/sonar/qualityprofiles.py +++ b/sonar/qualityprofiles.py @@ -263,7 +263,7 @@ def activate_rule(self, rule_key: str, severity: str = None, **params) -> bool: try: r = self.post("qualityprofiles/activate_rule", params=api_params) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while trying to activate rule %s in %s", util.http_error(e), rule_key, str(self)) + log.error("%s while trying to activate rule %s in %s", util.error_msg(e), rule_key, str(self)) return False return r.ok @@ -285,7 +285,7 @@ def activate_rules(self, ruleset: dict[str, str]) -> bool: ok = ok and self.activate_rule(rule_key=r_key, severity=sev) except (HTTPError, ConnectionError, RequestException) as e: ok = False - log.error("%s while activating rules in '%s'", util.http_error(e), r_key) + log.error("%s while activating rules in '%s'", util.error_msg(e), r_key) return ok def update(self, data: types.ObjectJsonRepr, queue: Queue) -> QualityProfile: diff --git a/sonar/rules.py b/sonar/rules.py index 1e63dc4f3..2435ea2ff 100644 --- a/sonar/rules.py +++ b/sonar/rules.py @@ -134,7 +134,7 @@ def get_object(cls, endpoint: platform.Platform, key: str) -> Rule: except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key=key, message=f"Rule key '{key}' does not exist") - log.error("%s while getting rule'%s'", utilities.http_error(e), key) + log.error("%s while getting rule'%s'", utilities.error_msg(e), key) return Rule(endpoint=endpoint, key=key, data=json.loads(r.text)["rule"]) @classmethod diff --git a/sonar/settings.py b/sonar/settings.py index 0a46d4970..ba40197f9 100644 --- a/sonar/settings.py +++ b/sonar/settings.py @@ -457,7 +457,7 @@ def set_new_code_period(endpoint: pf.Platform, nc_type: str, nc_value: str, proj except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.UnsupportedOperation(f"Can't set project new code period: {e.response.text}") - log.error("%s setting new code period of '%s'", util.http_error(e), str(project_key)) + log.error("%s setting new code period of '%s'", util.error_msg(e), str(project_key)) return False return ok @@ -490,7 +490,7 @@ def set_visibility(endpoint: pf.Platform, visibility: str, component: object = N except (HTTPError, ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.UnsupportedOperation(f"Can't set project default visibility: {e.response.text}") - log.error("%s setting new code period of '%s'", util.http_error(e), str(component)) + log.error("%s setting new code period of '%s'", util.error_msg(e), str(component)) return False @@ -504,7 +504,7 @@ def set_setting(endpoint: pf.Platform, key: str, value: any, component: object = try: s.set(value) except (HTTPError, ConnectionError, RequestException) as e: - log.error("%s while setting setting '%s'", util.http_error(e), key, str(component)) + log.error("%s while setting setting '%s'", util.error_msg(e), key, str(component)) return False except exceptions.UnsupportedOperation as e: log.error("Setting '%s' cannot be set: %s", key, e.message) diff --git a/sonar/sqobject.py b/sonar/sqobject.py index 07a5a4557..ea555521c 100644 --- a/sonar/sqobject.py +++ b/sonar/sqobject.py @@ -117,7 +117,7 @@ def __search_thread(queue: Queue) -> None: else: objects[obj[key_field]] = object_class(endpoint, obj[key_field], data=obj) except (HTTPError, ConnectionError, RequestException) as e: - log.critical("%s while searching %s, search skipped", utilities.http_error(e), object_class.__name__) + log.critical("%s while searching %s, search skipped", utilities.error_msg(e), object_class.__name__) queue.task_done() @@ -167,7 +167,7 @@ def delete_object(object: SqObject, api: str, params: types.ApiParams, map: dict if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: map.pop(object.uuid(), None) raise exceptions.ObjectNotFound(object.key, f"{str(object)} not found for delete") - log.error("%s while deleting object '%s'", utilities.http_error(e), str(object)) + log.error("%s while deleting object '%s'", utilities.error_msg(e), str(object)) raise diff --git a/sonar/utilities.py b/sonar/utilities.py index eb3f4245c..7dea790fa 100644 --- a/sonar/utilities.py +++ b/sonar/utilities.py @@ -442,7 +442,7 @@ def http_error_and_code(exception: requests.HTTPError) -> tuple[int, str]: return err_code, f"{tool_msg}: {sonar_error(response)}" -def http_error(exception: Exception) -> str: +def error_msg(exception: Exception) -> str: """Returns the error of an Sonar API HTTP response, or None if no error""" if isinstance(exception, requests.HTTPError): _, errmsg = http_error_and_code(exception) From 6841d03e6d1e4b04536b00a09ed8262e46165c1b Mon Sep 17 00:00:00 2001 From: Olivier Korach Date: Sat, 12 Oct 2024 16:09:07 +0200 Subject: [PATCH 5/8] Quality pass --- sonar/issues.py | 4 ++-- sonar/permissions/permissions.py | 3 +-- sonar/qualityprofiles.py | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/sonar/issues.py b/sonar/issues.py index d13975d32..7e4f8a636 100644 --- a/sonar/issues.py +++ b/sonar/issues.py @@ -35,7 +35,7 @@ import sonar.platform as pf from sonar.util.types import ApiParams, ApiPayload, ObjectJsonRepr, ConfigSettings -from sonar import users, sqobject, findings, changelog, projects, errcodes +from sonar import users, sqobject, findings, changelog, projects import sonar.utilities as util API_SET_TAGS = "issues/set_tags" @@ -732,7 +732,7 @@ def __search_thread(queue: Queue) -> None: i["pullRequest"] = page_params.get("pullRequest", None) issue_list[i["key"]] = get_object(endpoint=endpoint, key=i["key"], data=i) log.debug("Added %d issues in threaded search page %d", len(data["issues"]), page) - except (HTTPError, ConnectionError, RequestException, Exception) as e: + except (HTTPError, RequestException, Exception) as e: log.error("%s while searching issues, search may be incomplete", util.error_msg(e)) queue.task_done() diff --git a/sonar/permissions/permissions.py b/sonar/permissions/permissions.py index c9b189ec3..26bf1aafc 100644 --- a/sonar/permissions/permissions.py +++ b/sonar/permissions/permissions.py @@ -25,11 +25,10 @@ import json from abc import ABC, abstractmethod -from http import HTTPStatus from requests import HTTPError, RequestException import sonar.logging as log -from sonar import utilities, errcodes +from sonar import utilities from sonar.util import types from sonar.audit.rules import get_rule, RuleId from sonar.audit.problem import Problem diff --git a/sonar/qualityprofiles.py b/sonar/qualityprofiles.py index c1342962d..e2eef757f 100644 --- a/sonar/qualityprofiles.py +++ b/sonar/qualityprofiles.py @@ -23,7 +23,6 @@ import json from datetime import datetime -from http import HTTPStatus from queue import Queue from threading import Thread, Lock from requests import HTTPError, RequestException From de781d8dfe4edf2965194ad0f28fb2bd7fe55af8 Mon Sep 17 00:00:00 2001 From: Olivier Korach Date: Sat, 12 Oct 2024 16:11:20 +0200 Subject: [PATCH 6/8] Fix redundant exception --- cli/findings_export.py | 8 ++++---- cli/loc.py | 4 ++-- cli/measures_export.py | 2 +- sonar/app_branches.py | 4 ++-- sonar/applications.py | 8 ++++---- sonar/branches.py | 10 +++++----- sonar/devops.py | 2 +- sonar/hotspots.py | 2 +- sonar/measures.py | 4 ++-- sonar/organizations.py | 2 +- sonar/permissions/permission_templates.py | 2 +- sonar/permissions/permissions.py | 4 ++-- sonar/permissions/quality_permissions.py | 2 +- sonar/platform.py | 4 ++-- sonar/portfolio_reference.py | 2 +- sonar/portfolios.py | 10 +++++----- sonar/projects.py | 20 ++++++++++---------- sonar/qualitygates.py | 2 +- sonar/qualityprofiles.py | 4 ++-- sonar/rules.py | 2 +- sonar/settings.py | 6 +++--- sonar/sqobject.py | 4 ++-- 22 files changed, 54 insertions(+), 54 deletions(-) diff --git a/cli/findings_export.py b/cli/findings_export.py index 900eafbb0..da32f1b95 100755 --- a/cli/findings_export.py +++ b/cli/findings_export.py @@ -294,7 +294,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ findings_list = findings.export_findings( component.endpoint, component.key, branch=params.get("branch", None), pull_request=params.get("pullRequest", None) ) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.critical("%s while exporting findings of %s, skipped", util.error_msg(e), str(component)) findings_list = {} write_queue.put([findings_list, False]) @@ -323,7 +323,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ if (i_statuses or not status_list) and (i_resols or not resol_list) and (i_types or not type_list) and (i_sevs or not sev_list): try: findings_list = component.get_issues(filters=new_params) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.critical("%s while exporting issues of %s, skipped", util.error_msg(e), str(component)) findings_list = {} else: @@ -333,7 +333,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ if (h_statuses or not status_list) and (h_resols or not resol_list) and (h_types or not type_list) and (h_sevs or not sev_list): try: findings_list.update(component.get_hotspots(filters=new_params)) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while exporting hotspots of object key %s, skipped", util.error_msg(e), str(component)) else: log.debug("Status = %s, Types = %s, Resol = %s, Sev = %s", str(h_statuses), str(h_types), str(h_resols), str(h_sevs)) @@ -351,7 +351,7 @@ def store_findings(components_list: dict[str, object], params: ConfigSettings) - try: log.debug("Queue %s task %s put", str(my_queue), str(comp)) my_queue.put((comp, params.copy())) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.critical("%s while exporting findings of %s, skipped", util.error_msg(e), str(comp)) threads = params.get(options.NBR_THREADS, 4) diff --git a/cli/loc.py b/cli/loc.py index e0bf1ca00..b01f09b87 100644 --- a/cli/loc.py +++ b/cli/loc.py @@ -51,7 +51,7 @@ def __get_csv_row(o: object, **kwargs) -> tuple[list[str], str]: """Returns CSV row of object""" try: loc = o.loc() - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.warning("%s, LoC export of %s skipped", util.error_msg(e), str(o)) loc = "" arr = [o.key, loc] @@ -113,7 +113,7 @@ def __get_object_json_data(o: object, **kwargs) -> dict[str, str]: d = {parent_type: o.concerned_object.key, "branch": o.name, "ncloc": ""} try: d["ncloc"] = o.loc() - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.warning("%s, LoC export of %s skipped", util.error_msg(e), str(o)) if kwargs[options.WITH_NAME]: d[f"{parent_type}Name"] = o.name diff --git a/cli/measures_export.py b/cli/measures_export.py index d791781cc..1b20c06b8 100755 --- a/cli/measures_export.py +++ b/cli/measures_export.py @@ -282,7 +282,7 @@ def __get_measures(obj: object, wanted_metrics: types.KeyList, hist: bool) -> Un data.update(__get_json_measures_history(obj, wanted_metrics)) else: data.update(__get_object_measures(obj, wanted_metrics)) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s, measures export skipped for %s", util.error_msg(e), str(obj)) return None return data diff --git a/sonar/app_branches.py b/sonar/app_branches.py index 6197b5757..62b71d1b6 100644 --- a/sonar/app_branches.py +++ b/sonar/app_branches.py @@ -109,7 +109,7 @@ def create(cls, app: App, name: str, project_branches: list[Branch]) -> Applicat params["projectBranch"].append(br_name) try: app.endpoint.post(APIS["create"], params=params) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(f"app.App {app.key} branch '{name}", e.response.text) log.critical("%s while creating branch '%s' of '%s'", utilities.error_msg(e), name, str(app)) @@ -184,7 +184,7 @@ def update(self, name: str, project_branches: list[Branch]) -> bool: params["projectBranch"].append(br_name) try: ok = self.endpoint.post(APIS["update"], params=params).ok - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(str(self), e.response.text) log.error("%s while updating '%s'", utilities.error_msg(e), str(self)) diff --git a/sonar/applications.py b/sonar/applications.py index 5204fadcc..bed1adb40 100644 --- a/sonar/applications.py +++ b/sonar/applications.py @@ -90,7 +90,7 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Application: return _OBJECTS[uu] try: data = json.loads(endpoint.get(APIS["get"], params={"application": key}).text)["application"] - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key, f"Application key '{key}' not found") log.error("%s while getting app key '%s'", util.error_msg(e), key) @@ -133,7 +133,7 @@ def create(cls, endpoint: pf.Platform, key: str, name: str) -> Application: check_supported(endpoint) try: endpoint.post(APIS["create"], params={"key": key, "name": name}) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(key, e.response.text) log.critical("%s while creating app key '%s'", util.error_msg(e), key) @@ -150,7 +150,7 @@ def refresh(self) -> None: try: self.reload(json.loads(self.get("navigation/component", params={"component": self.key}).text)) self.reload(json.loads(self.get(APIS["get"], params=self.search_params()).text)["application"]) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: _OBJECTS.pop(self.uuid(), None) raise exceptions.ObjectNotFound(self.key, f"{str(self)} not found") @@ -388,7 +388,7 @@ def add_projects(self, project_list: list[str]) -> bool: try: r = self.post("applications/add_project", params={"application": self.key, "project": proj}) ok = ok and r.ok - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: log.warning("Project '%s' not found, can't be added to %s", proj, self) ok = False diff --git a/sonar/branches.py b/sonar/branches.py index c53ef38bf..466b8a986 100644 --- a/sonar/branches.py +++ b/sonar/branches.py @@ -89,7 +89,7 @@ def get_object(cls, concerned_object: projects.Project, branch_name: str) -> Bra return _OBJECTS[uu] try: data = json.loads(concerned_object.endpoint.get(APIS["list"], params={"project": concerned_object.key}).text) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"Project '{concerned_object.key}' not found") log.critical("%s while getting branch '%s' of %s", util.error_msg(e), branch_name, str(concerned_object)) @@ -129,7 +129,7 @@ def refresh(self) -> Branch: """ try: data = json.loads(self.get(APIS["list"], params={"project": self.concerned_object.key}).text) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.key, f"{str(self)} not found in SonarQube") log.error("%s while refreshing %s", util.error_msg(e), str(self)) @@ -185,7 +185,7 @@ def delete(self) -> bool: """ try: return sq.delete_object(self, APIS["delete"], {"branch": self.name, "project": self.concerned_object.key}, _OBJECTS) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: log.warning("Can't delete %s, it's the main branch", str(self)) else: @@ -202,7 +202,7 @@ def new_code(self) -> str: elif self._new_code is None: try: data = json.loads(self.get(api=APIS["get_new_code"], params={"project": self.concerned_object.key}).text) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.concerned_object.key, f"{str(self.concerned_object)} not found") log.error("%s while getting new code period of %s", util.error_msg(e), str(self)) @@ -265,7 +265,7 @@ def rename(self, new_name): log.info("Renaming main branch of %s from '%s' to '%s'", str(self.concerned_object), self.name, new_name) try: self.post(APIS["rename"], params={"project": self.concerned_object.key, "name": new_name}) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(HTTPError, e) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.concerned_object.key, f"str{self.concerned_object} not found") log.error("%s while renaming %s", util.error_msg(e), str(self)) diff --git a/sonar/devops.py b/sonar/devops.py index df8bac5c8..0461dab13 100644 --- a/sonar/devops.py +++ b/sonar/devops.py @@ -109,7 +109,7 @@ def create(cls, endpoint: platform.Platform, key: str, plt_type: str, url_or_wor elif plt_type == "bitbucketcloud": params.update({"clientSecret": _TO_BE_SET, "clientId": _TO_BE_SET, "workspace": url_or_workspace}) endpoint.post(_CREATE_API_BBCLOUD, params=params) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.BAD_REQUEST and endpoint.edition() in ("community", "developer"): log.warning("Can't set DevOps platform '%s', don't you have more that 1 of that type?", key) raise exceptions.UnsupportedOperation(f"Can't set DevOps platform '{key}', don't you have more that 1 of that type?") diff --git a/sonar/hotspots.py b/sonar/hotspots.py index 75392d4eb..f79d70312 100644 --- a/sonar/hotspots.py +++ b/sonar/hotspots.py @@ -402,7 +402,7 @@ def search(endpoint: pf.Platform, filters: types.ApiParams = None) -> dict[str, try: data = json.loads(endpoint.get(Hotspot.SEARCH_API, params=inline_filters, mute=(HTTPStatus.NOT_FOUND,)).text) nbr_hotspots = util.nbr_total_elements(data) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if e.response.status_code == HTTPStatus.NOT_FOUND: log.warning("No hotspots found with search params %s", str(inline_filters)) nbr_hotspots = 0 diff --git a/sonar/measures.py b/sonar/measures.py index a41fa3ff2..64f7a09fa 100644 --- a/sonar/measures.py +++ b/sonar/measures.py @@ -124,7 +124,7 @@ def get(concerned_object: object, metrics_list: KeyList, **kwargs) -> dict[str, try: data = json.loads(concerned_object.endpoint.get(Measure.API_READ, params={**kwargs, **params}).text) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"{str(concerned_object)} not found") log.error("%s while getting measures %s of %s", util.error_msg(e), str(metrics_list), str(concerned_object)) @@ -155,7 +155,7 @@ def get_history(concerned_object: object, metrics_list: KeyList, **kwargs) -> li try: data = json.loads(concerned_object.endpoint.get(Measure.API_HISTORY, params={**kwargs, **params}).text) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(concerned_object.key, f"{str(concerned_object)} not found") log.error("%s while getting measures %s history of %s", util.error_msg(e), str(metrics_list), str(concerned_object)) diff --git a/sonar/organizations.py b/sonar/organizations.py index 8fb3fdc9d..8a7470039 100644 --- a/sonar/organizations.py +++ b/sonar/organizations.py @@ -78,7 +78,7 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Organization: return _OBJECTS[uu] try: data = json.loads(endpoint.get(Organization.SEARCH_API, params={"organizations": key}).text) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key, f"Organization '{key}' not found") log.error("%s getting organization %s", util.error_msg(e), key) diff --git a/sonar/permissions/permission_templates.py b/sonar/permissions/permission_templates.py index db2a4545e..f0504807d 100644 --- a/sonar/permissions/permission_templates.py +++ b/sonar/permissions/permission_templates.py @@ -141,7 +141,7 @@ def set_as_default(self, what_list: list[str]) -> None: continue try: self.post("permissions/set_default_template", params={"templateId": self.key, "qualifier": qual}) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while setting %s as default", utilities.error_msg(e), str(self)) raise diff --git a/sonar/permissions/permissions.py b/sonar/permissions/permissions.py index 26bf1aafc..0374e3c88 100644 --- a/sonar/permissions/permissions.py +++ b/sonar/permissions/permissions.py @@ -239,7 +239,7 @@ def _get_api(self, api: str, perm_type: str, ret_field: str, **extra_params) -> else: counter += 1 page, nbr_pages = page + 1, utilities.nbr_pages(data) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while retrieving %s permissions", utilities.error_msg(e), str(self)) page += 1 return perms @@ -256,7 +256,7 @@ def _post_api(self, api: str, set_field: str, perms_dict: types.JsonPermissions, params["permission"] = p try: r = self.endpoint.post(api, params=params) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while setting permissions %s", utilities.error_msg(e), str(self)) result = result and r.ok return result diff --git a/sonar/permissions/quality_permissions.py b/sonar/permissions/quality_permissions.py index 13de9dd38..20439b9e5 100644 --- a/sonar/permissions/quality_permissions.py +++ b/sonar/permissions/quality_permissions.py @@ -76,7 +76,7 @@ def _get_api(self, api: str, perm_type: tuple[str, ...], ret_field: str, **extra data = json.loads(resp.text) perms += [p[ret_field] for p in data[perm_type]] page, nbr_pages = page + 1, utilities.nbr_pages(data) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while retrieving %s permissions", utilities.error_msg(e), str(self)) page += 1 return perms diff --git a/sonar/platform.py b/sonar/platform.py index a6e1a06e3..fc2676e6f 100644 --- a/sonar/platform.py +++ b/sonar/platform.py @@ -104,7 +104,7 @@ def __credentials(self) -> tuple[str, str]: def verify_connection(self) -> None: try: self.get("server/version") - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.critical("%s while verifying connection", util.error_msg(e)) raise exceptions.ConnectionError(util.sonar_error(e.response)) @@ -285,7 +285,7 @@ def sys_info(self) -> dict[str, any]: try: resp = self.get("system/info", mute=(HTTPStatus.INTERNAL_SERVER_ERROR,)) success = True - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: # Hack: SonarQube randomly returns Error 500 on this API, retry up to 10 times if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR and counter < 10: log.error("HTTP Error 500 for api/system/info, retrying...") diff --git a/sonar/portfolio_reference.py b/sonar/portfolio_reference.py index 87efd1030..fceca290d 100644 --- a/sonar/portfolio_reference.py +++ b/sonar/portfolio_reference.py @@ -73,7 +73,7 @@ def create(cls, reference: object, parent: object, params: types.ApiParams = Non try: parent.endpoint.post("views/add_portfolio", params={"portfolio": parent.key, "reference": reference.key}) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists log.critical("%s while creating portfolio reference to %s in %s", utilities.error_msg(e), str(reference), str(parent)) diff --git a/sonar/portfolios.py b/sonar/portfolios.py index d4a4168ca..ee176932e 100644 --- a/sonar/portfolios.py +++ b/sonar/portfolios.py @@ -262,7 +262,7 @@ def add_reference_subportfolio(self, reference: Portfolio) -> object: self.post("views/add_portfolio", params={"portfolio": self.key, "reference": reference.key}, mute=(HTTPStatus.BAD_REQUEST,)) else: self.post("views/add_local_view", params={"key": self.key, "ref_key": reference.key}, mute=(HTTPStatus.BAD_REQUEST,)) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: log.error("%s while adding reference subportfolio to %s", util.error_msg(e), str(self)) raise @@ -275,7 +275,7 @@ def add_standard_subportfolio(self, key: str, name: str, **kwargs) -> Portfolio: try: if self.endpoint.version() < (9, 3, 0): self.post("views/add_sub_view", params={"key": self.key, "name": name, "subKey": key}, mute=(HTTPStatus.BAD_REQUEST,)) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: log.error("%s while adding standard subportfolio to %s", util.error_msg(e), str(self)) raise @@ -523,7 +523,7 @@ def add_application_branch(self, app_key: str, branch: str = settings.DEFAULT_BR log.info("%s: Adding %s", str(self), str(app_branch)) params = {"key": self.key, "application": app_key, "branch": branch} self.post("views/add_application_branch", params=params, mute=(HTTPStatus.BAD_REQUEST,)) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: log.error("%s while adding application branch to %s", util.error_msg(e), str(self)) raise @@ -583,7 +583,7 @@ def get_project_list(self) -> list[str]: data = json.loads(self.get("api/measures/component_tree", params=params).text) nbr_projects = util.nbr_total_elements(data) proj_key_list += [c["refKey"] for c in data["components"]] - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while collecting projects from %s, stopping collection", util.error_msg(e), str(self)) break nbr_pages = util.nbr_pages(data) @@ -791,7 +791,7 @@ def export( exported_portfolios[k] = exp else: log.debug("Skipping export of %s, it's a standard sub-portfolio", str(p)) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while exporting %s, export will be empty for this portfolio", util.error_msg(e), str(p)) exported_portfolios[k] = {} i += 1 diff --git a/sonar/projects.py b/sonar/projects.py index 1a06f25da..5f2005f71 100644 --- a/sonar/projects.py +++ b/sonar/projects.py @@ -168,7 +168,7 @@ def get_object(cls, endpoint: pf.Platform, key: str) -> Project: log.error("Project key '%s' not found", key) raise exceptions.ObjectNotFound(key, f"Project key '{key}' not found") return cls.load(endpoint, data["components"][0]) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.FORBIDDEN: log.error("%s while getting project '%s'", util.error_msg(e), key) raise @@ -208,7 +208,7 @@ def create(cls, endpoint: pf.Platform, key: str, name: str) -> Project: """ try: endpoint.post(_CREATE_API, params={"project": key, "name": name}) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.ObjectAlreadyExists(key, e.response.text) log.error("%s while creating project '%s'", util.error_msg(e), key) @@ -380,7 +380,7 @@ def binding(self): resp = self.get("alm_settings/get_binding", params={"project": self.key}, mute=(HTTPStatus.NOT_FOUND,)) self._binding["has_binding"] = True self._binding["binding"] = json.loads(resp.text) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code in (HTTPStatus.NOT_FOUND, HTTPStatus.BAD_REQUEST): # Hack: 8.9 returns 404, 9.x returns 400 self._binding["has_binding"] = False @@ -559,7 +559,7 @@ def __audit_binding_valid(self, audit_settings: types.ConfigSettings) -> list[Pr try: _ = self.get("alm_settings/validate_binding", params={"project": self.key}) log.debug("%s binding is valid", str(self)) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: # Hack: 8.9 returns 404, 9.x returns 400 if isinstance(e, HTTPError) and e.response.status_code in (HTTPStatus.BAD_REQUEST, HTTPStatus.NOT_FOUND): return [Problem(get_rule(RuleId.PROJ_INVALID_BINDING), self, str(self))] @@ -619,7 +619,7 @@ def ci(self) -> str: data = json.loads(self.get("project_analyses/search", params={"project": self.key, "ps": 1}).text)["analyses"] if len(data) > 0: self._ci, self._revision = data[0].get("detectedCI", "unknown"), data[0].get("revision", "unknown") - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.warning("%s while getting %s CI tool", util.error_msg(e), str(self)) except KeyError: log.warning("KeyError, can't retrieve CI tool and revision") @@ -666,7 +666,7 @@ def audit(self, audit_settings: types.ConfigSettings) -> list[Problem]: problems += self._audit_bg_task(audit_settings) problems += self.__audit_binding_valid(audit_settings) problems += self.__audit_scanner(audit_settings) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.FORBIDDEN: log.error("Not enough permission to fully audit %s", str(self)) else: @@ -710,7 +710,7 @@ def export_async(self) -> Union[str, None]: log.info("Exporting %s (asynchronously)", str(self)) try: return json.loads(self.post("project_dump/export", params={"key": self.key}).text)["taskId"] - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while exporting zip of %s CI", util.error_msg(e), str(self)) return None @@ -1051,7 +1051,7 @@ def export(self, export_settings: types.ConfigSettings, settings_list: dict[str, if not export_settings.get("INCLUDE_INHERITED", False) and s.inherited: continue json_data.update(s.to_json()) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: errmsg = util.error_msg(e) log.error("Exception: %s while exporting %s, export of this project interrupted", errmsg, str(self)) json_data["error"] = f"{errmsg} while extracting project" @@ -1090,7 +1090,7 @@ def set_permissions(self, desired_permissions: types.ObjectJsonRepr) -> bool: try: self.permissions().set(desired_permissions) return True - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while setting permissions of %s", util.error_msg(e), str(self)) if not isinstance(e, HTTPError) or e.response.status_code != HTTPStatus.BAD_REQUEST: raise e @@ -1428,7 +1428,7 @@ def __audit_thread(queue: Queue[Project], results: list[Problem], audit_settings results.append(Problem(get_rule(RuleId.PROJ_DUPLICATE_BINDING), project, str(project), str(bindings[bindkey]))) else: bindings[bindkey] = project - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while auditing %s", util.error_msg(e), str(project)) queue.task_done() log.debug("%s audit complete", str(project)) diff --git a/sonar/qualitygates.py b/sonar/qualitygates.py index 365595683..d08251148 100644 --- a/sonar/qualitygates.py +++ b/sonar/qualitygates.py @@ -173,7 +173,7 @@ def projects(self) -> dict[str, projects.Project]: params["p"] = page try: resp = self.get(APIS["get_projects"], params=params) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(self.name, f"{str(self)} not found") log.error("%s while getting %s projects", util.error_msg(e), str(self)) diff --git a/sonar/qualityprofiles.py b/sonar/qualityprofiles.py index e2eef757f..be2516a14 100644 --- a/sonar/qualityprofiles.py +++ b/sonar/qualityprofiles.py @@ -261,7 +261,7 @@ def activate_rule(self, rule_key: str, severity: str = None, **params) -> bool: api_params["params"] = ";".join([f"{k}={v}" for k, v in params.items()]) try: r = self.post("qualityprofiles/activate_rule", params=api_params) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while trying to activate rule %s in %s", util.error_msg(e), rule_key, str(self)) return False return r.ok @@ -282,7 +282,7 @@ def activate_rules(self, ruleset: dict[str, str]) -> bool: ok = ok and self.activate_rule(rule_key=r_key, severity=sev, **r_data["params"]) else: ok = ok and self.activate_rule(rule_key=r_key, severity=sev) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: ok = False log.error("%s while activating rules in '%s'", util.error_msg(e), r_key) return ok diff --git a/sonar/rules.py b/sonar/rules.py index 2435ea2ff..7c4886e6e 100644 --- a/sonar/rules.py +++ b/sonar/rules.py @@ -131,7 +131,7 @@ def get_object(cls, endpoint: platform.Platform, key: str) -> Rule: log.debug("Reading rule key '%s'", key) try: r = endpoint.get(_DETAILS_API, params={"key": key}) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: raise exceptions.ObjectNotFound(key=key, message=f"Rule key '{key}' does not exist") log.error("%s while getting rule'%s'", utilities.error_msg(e), key) diff --git a/sonar/settings.py b/sonar/settings.py index ba40197f9..673b48bcd 100644 --- a/sonar/settings.py +++ b/sonar/settings.py @@ -454,7 +454,7 @@ def set_new_code_period(endpoint: pf.Platform, nc_type: str, nc_value: str, proj ok = ok and endpoint.post(API_SET, params={"key": "sonar.leak.period", "value": nc_value, "project": project_key}).ok else: ok = endpoint.post(API_NEW_CODE_SET, params={"type": nc_type, "value": nc_value, "project": project_key, "branch": branch}).ok - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.UnsupportedOperation(f"Can't set project new code period: {e.response.text}") log.error("%s setting new code period of '%s'", util.error_msg(e), str(project_key)) @@ -487,7 +487,7 @@ def set_visibility(endpoint: pf.Platform, visibility: str, component: object = N else: log.debug("Setting setting '%s' to value '%s'", PROJECT_DEFAULT_VISIBILITY, str(visibility)) return endpoint.post("projects/update_default_visibility", params={"projectVisibility": visibility}).ok - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.BAD_REQUEST: raise exceptions.UnsupportedOperation(f"Can't set project default visibility: {e.response.text}") log.error("%s setting new code period of '%s'", util.error_msg(e), str(component)) @@ -503,7 +503,7 @@ def set_setting(endpoint: pf.Platform, key: str, value: any, component: object = else: try: s.set(value) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while setting setting '%s'", util.error_msg(e), key, str(component)) return False except exceptions.UnsupportedOperation as e: diff --git a/sonar/sqobject.py b/sonar/sqobject.py index ea555521c..ed5bb5930 100644 --- a/sonar/sqobject.py +++ b/sonar/sqobject.py @@ -116,7 +116,7 @@ def __search_thread(queue: Queue) -> None: objects[obj[key_field]] = object_class.load(endpoint=endpoint, data=obj) else: objects[obj[key_field]] = object_class(endpoint, obj[key_field], data=obj) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.critical("%s while searching %s, search skipped", utilities.error_msg(e), object_class.__name__) queue.task_done() @@ -163,7 +163,7 @@ def delete_object(object: SqObject, api: str, params: types.ApiParams, map: dict map.pop(object.uuid(), None) log.info("Successfully deleted %s", str(object)) return r.ok - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: if isinstance(e, HTTPError) and e.response.status_code == HTTPStatus.NOT_FOUND: map.pop(object.uuid(), None) raise exceptions.ObjectNotFound(object.key, f"{str(object)} not found for delete") From e255519e51c35a3948182fc4355f8affd220aba9 Mon Sep 17 00:00:00 2001 From: Olivier Korach Date: Sat, 12 Oct 2024 16:23:49 +0200 Subject: [PATCH 7/8] Remove unused import HTTPError --- cli/findings_export.py | 8 ++++---- cli/loc.py | 2 +- cli/measures_export.py | 2 +- sonar/app_branches.py | 2 +- sonar/applications.py | 2 +- sonar/branches.py | 2 +- sonar/devops.py | 2 +- sonar/hotspots.py | 2 +- sonar/issues.py | 5 ++--- sonar/permissions/permission_templates.py | 2 +- sonar/permissions/permissions.py | 2 +- sonar/permissions/quality_permissions.py | 2 +- sonar/qualityprofiles.py | 2 +- sonar/utilities.py | 2 +- 14 files changed, 18 insertions(+), 19 deletions(-) diff --git a/cli/findings_export.py b/cli/findings_export.py index da32f1b95..900eafbb0 100755 --- a/cli/findings_export.py +++ b/cli/findings_export.py @@ -294,7 +294,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ findings_list = findings.export_findings( component.endpoint, component.key, branch=params.get("branch", None), pull_request=params.get("pullRequest", None) ) - except (ConnectionError, RequestException) as e: + except (HTTPError, ConnectionError, RequestException) as e: log.critical("%s while exporting findings of %s, skipped", util.error_msg(e), str(component)) findings_list = {} write_queue.put([findings_list, False]) @@ -323,7 +323,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ if (i_statuses or not status_list) and (i_resols or not resol_list) and (i_types or not type_list) and (i_sevs or not sev_list): try: findings_list = component.get_issues(filters=new_params) - except (ConnectionError, RequestException) as e: + except (HTTPError, ConnectionError, RequestException) as e: log.critical("%s while exporting issues of %s, skipped", util.error_msg(e), str(component)) findings_list = {} else: @@ -333,7 +333,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ if (h_statuses or not status_list) and (h_resols or not resol_list) and (h_types or not type_list) and (h_sevs or not sev_list): try: findings_list.update(component.get_hotspots(filters=new_params)) - except (ConnectionError, RequestException) as e: + except (HTTPError, ConnectionError, RequestException) as e: log.error("%s while exporting hotspots of object key %s, skipped", util.error_msg(e), str(component)) else: log.debug("Status = %s, Types = %s, Resol = %s, Sev = %s", str(h_statuses), str(h_types), str(h_resols), str(h_sevs)) @@ -351,7 +351,7 @@ def store_findings(components_list: dict[str, object], params: ConfigSettings) - try: log.debug("Queue %s task %s put", str(my_queue), str(comp)) my_queue.put((comp, params.copy())) - except (ConnectionError, RequestException) as e: + except (HTTPError, ConnectionError, RequestException) as e: log.critical("%s while exporting findings of %s, skipped", util.error_msg(e), str(comp)) threads = params.get(options.NBR_THREADS, 4) diff --git a/cli/loc.py b/cli/loc.py index b01f09b87..50e25f287 100644 --- a/cli/loc.py +++ b/cli/loc.py @@ -24,7 +24,7 @@ import sys import csv import datetime -from requests import HTTPError, RequestException +from requests import RequestException from cli import options import sonar.logging as log diff --git a/cli/measures_export.py b/cli/measures_export.py index 1b20c06b8..dfca37249 100755 --- a/cli/measures_export.py +++ b/cli/measures_export.py @@ -29,7 +29,7 @@ from typing import Union -from requests import HTTPError, RequestException +from requests import RequestException from sonar.util import types from cli import options import sonar.logging as log diff --git a/sonar/app_branches.py b/sonar/app_branches.py index 62b71d1b6..a45400de9 100644 --- a/sonar/app_branches.py +++ b/sonar/app_branches.py @@ -24,7 +24,7 @@ import json from http import HTTPStatus -from requests import HTTPError, RequestException +from requests import RequestException from requests.utils import quote import sonar.logging as log diff --git a/sonar/applications.py b/sonar/applications.py index bed1adb40..cc11c576c 100644 --- a/sonar/applications.py +++ b/sonar/applications.py @@ -26,7 +26,7 @@ from datetime import datetime from http import HTTPStatus from threading import Lock -from requests import HTTPError, RequestException +from requests import RequestException import sonar.logging as log import sonar.platform as pf diff --git a/sonar/branches.py b/sonar/branches.py index 466b8a986..48769ea47 100644 --- a/sonar/branches.py +++ b/sonar/branches.py @@ -364,7 +364,7 @@ def audit(self, audit_settings: types.ConfigSettings) -> list[Problem]: log.debug("Auditing %s", str(self)) try: return self.__audit_last_analysis(audit_settings) + self.__audit_zero_loc() + self.__audit_never_analyzed() - except (HTTPError, RequestException, Exception) as e: + except Exception as e: log.error("%s while auditing %s, audit skipped", util.error_msg(e), str(self)) else: log.debug("Branch audit disabled, skipping audit of %s", str(self)) diff --git a/sonar/devops.py b/sonar/devops.py index 0461dab13..e527d7f68 100644 --- a/sonar/devops.py +++ b/sonar/devops.py @@ -23,7 +23,7 @@ from http import HTTPStatus import json -from requests import HTTPError, RequestException +from requests import RequestException import sonar.logging as log from sonar.util import types diff --git a/sonar/hotspots.py b/sonar/hotspots.py index f79d70312..996c3bc21 100644 --- a/sonar/hotspots.py +++ b/sonar/hotspots.py @@ -24,7 +24,7 @@ import json import re from http import HTTPStatus -from requests import HTTPError, RequestException +from requests import RequestException import requests.utils import sonar.logging as log diff --git a/sonar/issues.py b/sonar/issues.py index 7e4f8a636..38202380c 100644 --- a/sonar/issues.py +++ b/sonar/issues.py @@ -29,7 +29,6 @@ from queue import Queue from threading import Thread import requests.utils -from requests import HTTPError, RequestException import sonar.logging as log import sonar.platform as pf @@ -732,7 +731,7 @@ def __search_thread(queue: Queue) -> None: i["pullRequest"] = page_params.get("pullRequest", None) issue_list[i["key"]] = get_object(endpoint=endpoint, key=i["key"], data=i) log.debug("Added %d issues in threaded search page %d", len(data["issues"]), page) - except (HTTPError, RequestException, Exception) as e: + except Exception as e: log.error("%s while searching issues, search may be incomplete", util.error_msg(e)) queue.task_done() @@ -858,7 +857,7 @@ def count_by_rule(endpoint: pf.Platform, **kwargs) -> dict[str, int]: if d["val"] not in rulecount: rulecount[d["val"]] = 0 rulecount[d["val"]] += d["count"] - except (HTTPError, Exception, RequestException) as e: + except Exception as e: log.error("%s while counting issues per rule, count may be incomplete", util.error_msg(e)) return rulecount diff --git a/sonar/permissions/permission_templates.py b/sonar/permissions/permission_templates.py index f0504807d..60492f048 100644 --- a/sonar/permissions/permission_templates.py +++ b/sonar/permissions/permission_templates.py @@ -22,7 +22,7 @@ import json import re -from requests import HTTPError, RequestException +from requests import RequestException import sonar.logging as log from sonar.util import types diff --git a/sonar/permissions/permissions.py b/sonar/permissions/permissions.py index 0374e3c88..d3d0b2c76 100644 --- a/sonar/permissions/permissions.py +++ b/sonar/permissions/permissions.py @@ -25,7 +25,7 @@ import json from abc import ABC, abstractmethod -from requests import HTTPError, RequestException +from requests import RequestException import sonar.logging as log from sonar import utilities diff --git a/sonar/permissions/quality_permissions.py b/sonar/permissions/quality_permissions.py index 20439b9e5..a7a7d7e1d 100644 --- a/sonar/permissions/quality_permissions.py +++ b/sonar/permissions/quality_permissions.py @@ -24,7 +24,7 @@ from typing import Optional import json -from requests import HTTPError, RequestException +from requests import RequestException from sonar.util import types import sonar.logging as log diff --git a/sonar/qualityprofiles.py b/sonar/qualityprofiles.py index be2516a14..d9745f7b1 100644 --- a/sonar/qualityprofiles.py +++ b/sonar/qualityprofiles.py @@ -25,7 +25,7 @@ from queue import Queue from threading import Thread, Lock -from requests import HTTPError, RequestException +from requests import RequestException import requests.utils import sonar.logging as log diff --git a/sonar/utilities.py b/sonar/utilities.py index 7dea790fa..ce9fb766a 100644 --- a/sonar/utilities.py +++ b/sonar/utilities.py @@ -52,7 +52,7 @@ def check_last_version(package_url: str) -> None: try: r = requests.get(url=package_url, headers={"Accept": "application/vnd.pypi.simple.v1+json"}, timeout=10) r.raise_for_status() - except (requests.RequestException, requests.HTTPError, requests.Timeout) as e: + except Exception as e: log.info("Can't access pypi.org, error %s", str(e)) return txt_version = json.loads(r.text)["versions"][-1] From f867691c33d355386221f10485df26e6a9502df8 Mon Sep 17 00:00:00 2001 From: Olivier Korach Date: Sat, 12 Oct 2024 19:50:17 +0200 Subject: [PATCH 8/8] Quality pass --- cli/findings_export.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cli/findings_export.py b/cli/findings_export.py index 900eafbb0..da32f1b95 100755 --- a/cli/findings_export.py +++ b/cli/findings_export.py @@ -294,7 +294,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ findings_list = findings.export_findings( component.endpoint, component.key, branch=params.get("branch", None), pull_request=params.get("pullRequest", None) ) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.critical("%s while exporting findings of %s, skipped", util.error_msg(e), str(component)) findings_list = {} write_queue.put([findings_list, False]) @@ -323,7 +323,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ if (i_statuses or not status_list) and (i_resols or not resol_list) and (i_types or not type_list) and (i_sevs or not sev_list): try: findings_list = component.get_issues(filters=new_params) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.critical("%s while exporting issues of %s, skipped", util.error_msg(e), str(component)) findings_list = {} else: @@ -333,7 +333,7 @@ def __get_component_findings(queue: Queue[tuple[object, ConfigSettings]], write_ if (h_statuses or not status_list) and (h_resols or not resol_list) and (h_types or not type_list) and (h_sevs or not sev_list): try: findings_list.update(component.get_hotspots(filters=new_params)) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.error("%s while exporting hotspots of object key %s, skipped", util.error_msg(e), str(component)) else: log.debug("Status = %s, Types = %s, Resol = %s, Sev = %s", str(h_statuses), str(h_types), str(h_resols), str(h_sevs)) @@ -351,7 +351,7 @@ def store_findings(components_list: dict[str, object], params: ConfigSettings) - try: log.debug("Queue %s task %s put", str(my_queue), str(comp)) my_queue.put((comp, params.copy())) - except (HTTPError, ConnectionError, RequestException) as e: + except (ConnectionError, RequestException) as e: log.critical("%s while exporting findings of %s, skipped", util.error_msg(e), str(comp)) threads = params.get(options.NBR_THREADS, 4)