Skip to content

Commit

Permalink
Add findings level to script tasks
Browse files Browse the repository at this point in the history
update schema
update tests

Signed-off-by: Andrea Waltlova <[email protected]>
  • Loading branch information
andywaltlova committed Apr 12, 2024
1 parent 3f39f63 commit db7bc32
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 93 deletions.
75 changes: 75 additions & 0 deletions schemas/leapp_schema_2.0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
"title": "Leapp pre-upgrade script schema",
"description": "Script is expected to set up Leapp and run pre-upgrade analysis. This schema defines the output format that is expected by Red Hat Insights Task UI.",
"type": "object",
"properties": {
"alert": {
"type": "boolean"
},
"error": {
"type": "boolean"
},
"status": {
"$ref": "#/$defs/status_codes"
},
"report": {
"type": "string"
},
"message": {
"type": "string"
},
"report_json": {
"oneOf": [
{
"type": "null"
},
{
"type": "object",
"properties": {
"entries": {
"type": "object"
},
"tasks_format_version": {
"type": "string"
},
"tasks_format_id": {
"type": "string"
}
},
"required": [
"entries",
"tasks_format_version",
"tasks_format_id"
]
}
]
},
"findings_level": {
"type": "integer",
"minimum": 0,
"maximum": 10
}
},
"required": [
"alert",
"error",
"status",
"message",
"report",
"report_json",
"findings_level"
],
"additionalProperties": false,
"$defs": {
"status_codes": {
"description": "The severity of the results and messages",
"type": "string",
"enum": [
"SUCCESS",
"INFO",
"WARNING",
"ERROR"
]
}
}
}
25 changes: 15 additions & 10 deletions scripts/leapp_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,11 @@ class OutputCollector(object):
# Nine and six is reasonable in this case.

def __init__(
self, status="", message="", report="", entries=None, alert=False, error=False
self, status="", message="", report="", entries=None, alert=False, error=False, findings_level=1,
):
self.status = status
self.status = status # empty default, to be set based on script results
self.alert = alert # true if error true or if pre-upgrade inhibited
self.findings_level = findings_level # value between 1-10

# NOTE: currently false everywhere
# here for consistency with conversions scripts
Expand Down Expand Up @@ -81,6 +82,7 @@ def to_dict(self):
"status": self.status,
"alert": self.alert,
"error": self.error,
"findings_level": self.findings_level,
"message": self.message,
"report": self.report,
"report_json": self.report_json,
Expand Down Expand Up @@ -305,14 +307,9 @@ def _find_highest_report_level(entries):
Gather status codes from entries.
"""
print("Collecting and combining report status.")
action_level_combined = [value["severity"] for value in entries]

valid_action_levels = [
level for level in action_level_combined if level in STATUS_CODE
]
valid_action_levels.sort(key=lambda status: STATUS_CODE[status], reverse=True)
return STATUS_CODE_NAME_MAP[valid_action_levels[0]]

valid_entries_levels = [value["severity"] for value in entries if value["severity"] in STATUS_CODE]
valid_entries_levels.sort(key=lambda status: STATUS_CODE[status], reverse=True)
return STATUS_CODE_NAME_MAP[valid_entries_levels[0]]

def parse_results(output, reboot_required=False):
print("Processing {} results ...".format(SCRIPT_TYPE.title()))
Expand All @@ -321,6 +318,7 @@ def parse_results(output, reboot_required=False):
message = "Can't open json report at " + JSON_REPORT_PATH
alert = True
status = "ERROR"
findings_level = 1

print("Reading JSON report")
if os.path.exists(JSON_REPORT_PATH):
Expand Down Expand Up @@ -361,6 +359,10 @@ def parse_results(output, reboot_required=False):
"" if len(report_entries) == 1 else "s",
)
)
if error_count > 0:
findings_level = 7
if inhibitor_count > 0:
findings_level = 5

if reboot_required:
message = (
Expand All @@ -378,6 +380,7 @@ def parse_results(output, reboot_required=False):
output.report_json = report_json
output.alert = alert
output.message = message
output.findings_level = findings_level

print("Reading TXT report")
report_txt = "Not found"
Expand Down Expand Up @@ -456,6 +459,7 @@ def main():
error=False,
message=exception.message,
report=exception.report,
findings_level=7,
)
except Exception as exception:
print(str(exception))
Expand All @@ -465,6 +469,7 @@ def main():
error=False,
message="An unexpected error occurred. Expand the row for more details.",
report=str(exception),
findings_level=10,
)
finally:
print("### JSON START ###")
Expand Down
38 changes: 14 additions & 24 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ def test_main_invalid_script_type(capsys):
in captured.out
)
assert "Exiting because RHC_WORKER_LEAPP_SCRIPT_TYPE='TEST'" in captured.out
assert '"findings_level": 7' in captured.out


@patch("scripts.leapp_script.SCRIPT_TYPE", "PREUPGRADE")
Expand All @@ -24,9 +25,7 @@ def test_main_invalid_script_type(capsys):
@patch("scripts.leapp_script.is_non_eligible_releases")
@patch("scripts.leapp_script.setup_leapp")
@patch("scripts.leapp_script.update_insights_inventory")
@patch("scripts.leapp_script.OutputCollector")
def test_main_non_eligible_release_preupgrade(
mock_output_collector,
mock_update_insights_inventory,
mock_setup_leapp,
mock_is_non_eligible_releases,
Expand All @@ -35,16 +34,15 @@ def test_main_non_eligible_release_preupgrade(
):
mock_get_rhel_version.return_value = ("rhel", "6.9")
mock_is_non_eligible_releases.return_value = True
mock_output_collector.return_value = OutputCollector(entries=["non-empty"])

main()

captured = capsys.readouterr()
assert 'Exiting because distribution="rhel" and version="6.9"' in captured.out
assert '"findings_level": 7' in captured.out

mock_get_rhel_version.assert_called_once()
mock_is_non_eligible_releases.assert_called_once()
mock_output_collector.assert_called_once()
mock_setup_leapp.assert_not_called()
mock_update_insights_inventory.assert_not_called()

Expand All @@ -60,9 +58,7 @@ def test_main_non_eligible_release_preupgrade(
@patch("scripts.leapp_script.remove_previous_reports")
@patch("scripts.leapp_script.execute_operation")
@patch("scripts.leapp_script.update_insights_inventory")
@patch("scripts.leapp_script.OutputCollector")
def test_main_eligible_release_preupgrade(
mock_output_collector,
def test_main_eligible_release_preupgrade_success(
mock_update_insights_inventory,
mock_execute_operation,
mock_remove_previous_reports,
Expand All @@ -78,11 +74,11 @@ def test_main_eligible_release_preupgrade(
mock_is_non_eligible_releases.return_value = False
mock_setup_leapp.return_value = [{"leapp_pkg": "to_install"}]
mock_should_use_no_rhsm_check.return_value = True
mock_output_collector.return_value = OutputCollector(entries=["non-empty"])

main()
captured = capsys.readouterr()
assert "Operation Preupgrade finished successfully." in captured.out
assert '"findings_level": 1' in captured.out

mock_setup_leapp.assert_called_once()
mock_should_use_no_rhsm_check.assert_called_once()
Expand All @@ -105,9 +101,7 @@ def test_main_eligible_release_preupgrade(
@patch("scripts.leapp_script.remove_previous_reports")
@patch("scripts.leapp_script.execute_operation")
@patch("scripts.leapp_script.update_insights_inventory")
@patch("scripts.leapp_script.OutputCollector")
def test_main_eligible_release_upgrade(
mock_output_collector,
def test_main_eligible_release_upgrade_success(
mock_update_insights_inventory,
mock_execute_operation,
mock_remove_previous_reports,
Expand All @@ -124,14 +118,14 @@ def test_main_eligible_release_upgrade(
mock_is_non_eligible_releases.return_value = False
mock_setup_leapp.return_value = [{"leapp_pkg": "to_install"}]
mock_should_use_no_rhsm_check.return_value = True
mock_output_collector.return_value = OutputCollector(entries=["non-empty"])
mock_execute_operation.return_value = (
"LOREM IPSUM\nTEST" + REBOOT_GUIDANCE_MESSAGE + "TEST\nDOLOR SIT AMET"
)

main()
captured = capsys.readouterr()
assert "Operation Upgrade finished successfully." in captured.out
assert '"findings_level": 1' in captured.out

mock_setup_leapp.assert_called_once()
mock_should_use_no_rhsm_check.assert_called_once()
Expand All @@ -155,9 +149,7 @@ def test_main_eligible_release_upgrade(
@patch("scripts.leapp_script.remove_previous_reports")
@patch("scripts.leapp_script.execute_operation")
@patch("scripts.leapp_script.update_insights_inventory")
@patch("scripts.leapp_script.OutputCollector")
def test_main_upgrade_not_sucessfull(
mock_output_collector,
mock_update_insights_inventory,
mock_execute_operation,
mock_remove_previous_reports,
Expand All @@ -174,13 +166,15 @@ def test_main_upgrade_not_sucessfull(
mock_is_non_eligible_releases.return_value = False
mock_setup_leapp.return_value = [{"leapp_pkg": "to_install"}]
mock_should_use_no_rhsm_check.return_value = True
mock_output_collector.return_value = OutputCollector(entries=["non-empty"])
mock_execute_operation.return_value = "LOREM IPSUM\n" + "\nDOLOR SIT AMET"

main()
captured = capsys.readouterr()
assert "Operation Upgrade finished successfully." in captured.out

# NOTE: parse_results is mocked so findings_level doesn't get set
assert '"findings_level": 1' in captured.out

mock_setup_leapp.assert_called_once()
mock_should_use_no_rhsm_check.assert_called_once()
mock_install_rhui.assert_called_once()
Expand All @@ -202,11 +196,9 @@ def test_main_upgrade_not_sucessfull(
@patch("scripts.leapp_script.remove_previous_reports")
@patch("scripts.leapp_script.execute_operation")
@patch("scripts.leapp_script.update_insights_inventory")
@patch("scripts.leapp_script.OutputCollector")
@patch("scripts.leapp_script.run_subprocess")
def test_main_setup_leapp_not_sucessfull(
mock_run_subprocess,
mock_output_collector,
mock_update_insights_inventory,
mock_execute_operation,
mock_remove_previous_reports,
Expand All @@ -221,11 +213,11 @@ def test_main_setup_leapp_not_sucessfull(
mock_get_rhel_version.return_value = ("rhel", "7.9")
mock_is_non_eligible_releases.return_value = False
mock_run_subprocess.return_value = ("Installation failed", 1)
mock_output_collector.return_value = OutputCollector(entries=["non-empty"])

main()
captured = capsys.readouterr()
assert "Installation of leapp failed with code '1'" in captured.out
assert '"findings_level": 7' in captured.out

mock_should_use_no_rhsm_check.assert_not_called()
mock_install_rhui.assert_not_called()
Expand All @@ -247,11 +239,9 @@ def test_main_setup_leapp_not_sucessfull(
@patch("scripts.leapp_script.remove_previous_reports")
@patch("scripts.leapp_script.execute_operation")
@patch("scripts.leapp_script.update_insights_inventory")
@patch("scripts.leapp_script.OutputCollector")
@patch("scripts.leapp_script.run_subprocess")
def test_main_install_corresponding_pkgs_not_sucessfull(
mock_run_subprocess,
mock_output_collector,
mock_update_insights_inventory,
mock_execute_operation,
mock_remove_previous_reports,
Expand All @@ -267,14 +257,14 @@ def test_main_install_corresponding_pkgs_not_sucessfull(
mock_is_non_eligible_releases.return_value = False
mock_run_subprocess.return_value = ("Installation failed", 1)
mock_setup_leapp.return_value = [{"leapp_pkg": "to_install"}]
mock_output_collector.return_value = OutputCollector(entries=["non-empty"])

main()
captured = capsys.readouterr()
assert (
"Installation of to_install (coresponding pkg to '{'leapp_pkg': 'to_install'}') failed with exit code 1 and output: Installation failed."
in captured.out
)
assert '"findings_level": 7' in captured.out

mock_setup_leapp.assert_called_once()
mock_should_use_no_rhsm_check.assert_called_once()
Expand All @@ -296,11 +286,9 @@ def test_main_install_corresponding_pkgs_not_sucessfull(
@patch("scripts.leapp_script.install_leapp_pkg_corresponding_to_installed_rhui")
@patch("scripts.leapp_script.remove_previous_reports")
@patch("scripts.leapp_script.execute_operation")
@patch("scripts.leapp_script.OutputCollector")
@patch("scripts.leapp_script.run_subprocess")
def test_main_update_inventory_not_sucessfull(
mock_run_subprocess,
mock_output_collector,
mock_execute_operation,
mock_remove_previous_reports,
mock_should_use_no_rhsm_check,
Expand All @@ -316,7 +304,6 @@ def test_main_update_inventory_not_sucessfull(
mock_is_non_eligible_releases.return_value = False
mock_setup_leapp.return_value = [{"leapp_pkg": "to_install"}]
mock_should_use_no_rhsm_check.return_value = True
mock_output_collector.return_value = OutputCollector(entries=["non-empty"])
mock_execute_operation.return_value = "LOREM IPSUM\n" + "\nDOLOR SIT AMET"
mock_run_subprocess.return_value = ("Installation failed", 1)

Expand All @@ -325,6 +312,9 @@ def test_main_update_inventory_not_sucessfull(
assert "Updating system status in Red Hat Insights." in captured.out
assert "System registration failed with exit code 1." in captured.out

# NOTE: parse_results is mocked so no findings_level is set
assert '"findings_level": 1' in captured.out

mock_setup_leapp.assert_called_once()
mock_should_use_no_rhsm_check.assert_called_once()
mock_install_rhui.assert_called_once()
Expand Down
Loading

0 comments on commit db7bc32

Please sign in to comment.