Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RHELC-1164] Update RHSM custom facts during analysis #1043

Merged
merged 5 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions convert2rhel/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ def main_locked():

except _AnalyzeExit:
breadcrumbs.breadcrumbs.finish_collection(success=True)
# Update RHSM custom facts only when this returns False. Otherwise,
# sub-man get uninstalled and the data is removed from the RHSM server.
if not subscription.should_subscribe():
subscription.update_rhsm_custom_facts()

rollback_changes()

Expand Down Expand Up @@ -189,6 +193,11 @@ def _handle_main_exceptions(process_phase, pre_conversion_results=None):
if process_phase == ConversionPhase.POST_CLI:
loggerinst.info(no_changes_msg)
elif process_phase == ConversionPhase.PRE_PONR_CHANGES:
# Update RHSM custom facts only when this returns False. Otherwise,
# sub-man get uninstalled and the data is removed from the RHSM server.
if not subscription.should_subscribe():
subscription.update_rhsm_custom_facts()

rollback_changes()
if pre_conversion_results is None:
loggerinst.info("\nConversion interrupted before analysis of system completed. Report not generated.\n")
Expand Down
72 changes: 72 additions & 0 deletions convert2rhel/unit_tests/main_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ def test_main_traceback_before_action_completion(self, monkeypatch, caplog, tmp_

# Mock the rollback calls
finish_collection_mock = mock.Mock()
should_subscribe_mock = mock.Mock(side_effect=lambda: False)
update_rhsm_custom_facts_mock = mock.Mock()
rollback_changes_mock = mock.Mock()
summary_as_json_mock = mock.Mock()

Expand All @@ -384,6 +386,8 @@ def test_main_traceback_before_action_completion(self, monkeypatch, caplog, tmp_
monkeypatch.setattr(pkgmanager, "clean_yum_metadata", clean_yum_metadata_mock)
monkeypatch.setattr(actions, "run_actions", run_actions_mock)
monkeypatch.setattr(breadcrumbs, "finish_collection", finish_collection_mock)
monkeypatch.setattr(subscription, "should_subscribe", should_subscribe_mock)
monkeypatch.setattr(subscription, "update_rhsm_custom_facts", update_rhsm_custom_facts_mock)
monkeypatch.setattr(main, "rollback_changes", rollback_changes_mock)
monkeypatch.setattr(report, "summary_as_json", summary_as_json_mock)
monkeypatch.setattr(report, "summary_as_txt", summary_as_txt_mock)
Expand All @@ -400,6 +404,8 @@ def test_main_traceback_before_action_completion(self, monkeypatch, caplog, tmp_
assert run_actions_mock.call_count == 1
assert clear_versionlock_mock.call_count == 1
assert finish_collection_mock.call_count == 1
assert should_subscribe_mock.call_count == 1
assert update_rhsm_custom_facts_mock.call_count == 1
assert rollback_changes_mock.call_count == 1
assert summary_as_json_mock.call_count == 0
assert summary_as_txt_mock.call_count == 0
Expand Down Expand Up @@ -427,6 +433,8 @@ def test_main_rollback_pre_ponr_changes_phase(self, monkeypatch, caplog, tmp_pat

# Mock the rollback calls
finish_collection_mock = mock.Mock()
should_subscribe_mock = mock.Mock(side_effect=lambda: False)
update_rhsm_custom_facts_mock = mock.Mock()
rollback_changes_mock = mock.Mock()
summary_as_json_mock = mock.Mock()

Expand All @@ -445,6 +453,8 @@ def test_main_rollback_pre_ponr_changes_phase(self, monkeypatch, caplog, tmp_pat
monkeypatch.setattr(report, "summary", report_summary_mock)
monkeypatch.setattr(actions, "find_actions_of_severity", find_actions_of_severity_mock)
monkeypatch.setattr(breadcrumbs, "finish_collection", finish_collection_mock)
monkeypatch.setattr(subscription, "should_subscribe", should_subscribe_mock)
monkeypatch.setattr(subscription, "update_rhsm_custom_facts", update_rhsm_custom_facts_mock)
monkeypatch.setattr(main, "rollback_changes", rollback_changes_mock)
monkeypatch.setattr(report, "summary_as_json", summary_as_json_mock)
monkeypatch.setattr(report, "summary_as_txt", summary_as_txt_mock)
Expand All @@ -463,12 +473,68 @@ def test_main_rollback_pre_ponr_changes_phase(self, monkeypatch, caplog, tmp_pat
assert find_actions_of_severity_mock.call_count == 1
assert clear_versionlock_mock.call_count == 1
assert finish_collection_mock.call_count == 1
assert should_subscribe_mock.call_count == 1
assert update_rhsm_custom_facts_mock.call_count == 1
assert rollback_changes_mock.call_count == 1
assert summary_as_json_mock.call_count == 1
assert summary_as_txt_mock.call_count == 1
assert caplog.records[-3].message == "Conversion failed."
assert caplog.records[-3].levelname == "CRITICAL"

def test_main_rollback_analyze_exit_phase_without_subman(self, global_tool_opts, monkeypatch, tmp_path):
"""
This test is the opposite of
`py:test_main_rollback_analyze_exit_phase`, where we are checking the
case that the system needs to be registered during the analyze.

If that's the case, we don't want to call the update_rhsm_custom_facts
as the system will be unregistered in the end.
"""
mocks = (
(applock, "_DEFAULT_LOCK_DIR", str(tmp_path)),
(utils, "require_root", mock.Mock()),
(main, "initialize_file_logging", mock.Mock()),
(toolopts, "CLI", mock.Mock()),
(main, "show_eula", mock.Mock()),
(breadcrumbs, "print_data_collection", mock.Mock()),
(system_info, "resolve_system_info", mock.Mock()),
(system_info, "print_system_information", mock.Mock()),
(breadcrumbs, "collect_early_data", mock.Mock()),
(pkghandler, "clear_versionlock", mock.Mock()),
(pkgmanager, "clean_yum_metadata", mock.Mock()),
(actions, "run_actions", mock.Mock()),
(report, "summary", mock.Mock()),
(breadcrumbs, "finish_collection", mock.Mock()),
(subscription, "should_subscribe", mock.Mock(side_effect=lambda: True)),
(subscription, "update_rhsm_custom_facts", mock.Mock()),
(main, "rollback_changes", mock.Mock()),
(os, "environ", {"CONVERT2RHEL_EXPERIMENTAL_ANALYSIS": 1}),
(report, "summary_as_json", mock.Mock()),
(report, "summary_as_txt", mock.Mock()),
)
global_tool_opts.activity = "analysis"
for module, function, value in mocks:
monkeypatch.setattr(module, function, value)

assert main.main() == 0
assert utils.require_root.call_count == 1
assert toolopts.CLI.call_count == 1
assert main.show_eula.call_count == 1
assert breadcrumbs.print_data_collection.call_count == 1
assert system_info.resolve_system_info.call_count == 1
assert system_info.print_system_information.call_count == 1
assert breadcrumbs.collect_early_data.call_count == 1
assert pkghandler.clear_versionlock.call_count == 1
assert pkgmanager.clean_yum_metadata.call_count == 1
assert actions.run_actions.call_count == 1
assert report.summary.call_count == 1
assert breadcrumbs.finish_collection.call_count == 1
assert subscription.should_subscribe.call_count == 1
assert subscription.update_rhsm_custom_facts.call_count == 0
assert main.rollback_changes.call_count == 1
assert report.summary_as_json.call_count == 1
assert report.summary_as_txt.call_count == 1

def test_main_rollback_analyze_exit_phase(self, global_tool_opts, monkeypatch, tmp_path):
require_root_mock = mock.Mock()
initialize_file_logging_mock = mock.Mock()
Expand All @@ -487,6 +553,8 @@ def test_main_rollback_analyze_exit_phase(self, global_tool_opts, monkeypatch, t

# Mock the rollback calls
finish_collection_mock = mock.Mock()
should_subscribe_mock = mock.Mock(side_effect=lambda: False)
update_rhsm_custom_facts_mock = mock.Mock()
rollback_changes_mock = mock.Mock()

monkeypatch.setattr(applock, "_DEFAULT_LOCK_DIR", str(tmp_path))
Expand All @@ -503,6 +571,8 @@ def test_main_rollback_analyze_exit_phase(self, global_tool_opts, monkeypatch, t
monkeypatch.setattr(actions, "run_actions", run_actions_mock)
monkeypatch.setattr(report, "summary", report_summary_mock)
monkeypatch.setattr(breadcrumbs, "finish_collection", finish_collection_mock)
monkeypatch.setattr(subscription, "should_subscribe", should_subscribe_mock)
monkeypatch.setattr(subscription, "update_rhsm_custom_facts", update_rhsm_custom_facts_mock)
monkeypatch.setattr(main, "rollback_changes", rollback_changes_mock)
monkeypatch.setattr(os, "environ", {"CONVERT2RHEL_EXPERIMENTAL_ANALYSIS": 1})
monkeypatch.setattr(report, "summary_as_json", summary_as_json_mock)
Expand All @@ -522,6 +592,8 @@ def test_main_rollback_analyze_exit_phase(self, global_tool_opts, monkeypatch, t
assert report_summary_mock.call_count == 1
assert clear_versionlock_mock.call_count == 1
assert finish_collection_mock.call_count == 1
assert should_subscribe_mock.call_count == 1
assert update_rhsm_custom_facts_mock.call_count == 1
assert rollback_changes_mock.call_count == 1
assert summary_as_json_mock.call_count == 1
assert summary_as_txt_mock.call_count == 1
Expand Down
20 changes: 20 additions & 0 deletions tests/integration/tier0/non-destructive/rhsm-facts/main.fmf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
summary+: |
RHSM facts update when in analysis mode
description+: |
Verify that the subscription-manager facts command is called after the
analysis is done (either succeeding or failling).

/rhsm_facts_update_in_analysis:
summary+: |
RHSM facts update after analysis
description+: |
This test verifies that the RHSM facts are uploaded when running
convert2rhel with analysis option.
Comment on lines +8 to +12
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just duplicating the summary and description from the root of the path in the file.
Could be consolidated, I wouldn't block the merge on this though.

tag+:
- test-rhsm-facts-called-in-analysis
test: |
pytest -svv -m test_rhsm_facts_called_in_analysis
adjust+:
- enabled: false
when: distro == oracle-7, oracle-8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
when: distro == oracle-7, oracle-8
when: distro == oracle

The filtering calls the startswith() method, I believe, so no need to include both.
Again not a blocker, will fix in a different PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, thanks!

because: RHSM package not available in oracle repos
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pytest


@pytest.mark.test_rhsm_facts_called_in_analysis
def test_rhsm_facts_called_after_analysis(convert2rhel, pre_registered):
"""
Verify that the RHSM custom facts are uploaded after the analysis is done.
"""
with convert2rhel("analyze -y --debug") as c2r:
# Verify that the analysis report is printed
c2r.expect("Updating RHSM custom facts collected during the conversion.", timeout=600)
c2r.expect("RHSM custom facts uploaded successfully.", timeout=600)

# The analysis should exit with 0, if it finishes successfully
assert c2r.exitstatus == 0