-
Notifications
You must be signed in to change notification settings - Fork 138
Add foremanctl restore test cases in robottelo #22300
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||||||||||||||||||||||||||||||||||
| """Tests for foremanctl backup functionality | ||||||||||||||||||||||||||||||||||||||
| """Tests for foremanctl backup and restore functionality | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :Requirement: Installation | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
@@ -16,6 +16,8 @@ | |||||||||||||||||||||||||||||||||||||
| from fauxfactory import gen_string | ||||||||||||||||||||||||||||||||||||||
| import pytest | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| from robottelo.config import settings | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| pytestmark = [pytest.mark.foremanctl] | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| BACKUP_DIR = '/tmp/' | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -31,6 +33,23 @@ def get_exp_files(module_target_sat, skip_pulp=False): | |||||||||||||||||||||||||||||||||||||
| return expected_files | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| def _create_backup(sat, subdir): | ||||||||||||||||||||||||||||||||||||||
| """Run foremanctl backup and return the timestamped backup subdirectory path.""" | ||||||||||||||||||||||||||||||||||||||
| result = sat.execute( | ||||||||||||||||||||||||||||||||||||||
| f'foremanctl backup {subdir} --wait-for-tasks', | ||||||||||||||||||||||||||||||||||||||
| timeout='30m', | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| assert result.status == 0, f'foremanctl backup failed:\n{result.stdout}\n{result.stderr}' | ||||||||||||||||||||||||||||||||||||||
| result = sat.execute(f'test -d {subdir}') | ||||||||||||||||||||||||||||||||||||||
| assert result.status == 0, f'Backup directory {subdir} was not created' | ||||||||||||||||||||||||||||||||||||||
| backup_dir = re.findall(rf'{subdir}/foreman-backup-\S+', result.stdout) | ||||||||||||||||||||||||||||||||||||||
| if not backup_dir: | ||||||||||||||||||||||||||||||||||||||
| ls_result = sat.execute(f'ls -d {subdir}/foreman-backup-*') | ||||||||||||||||||||||||||||||||||||||
| assert ls_result.status == 0, f'No foreman-backup-* subdirectory found in {subdir}' | ||||||||||||||||||||||||||||||||||||||
| backup_dir = ls_result.stdout.strip().splitlines() | ||||||||||||||||||||||||||||||||||||||
| return backup_dir[0] | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| def test_positive_offline_backup(module_target_sat, setup_backup_tests): | ||||||||||||||||||||||||||||||||||||||
| """Verify foremanctl backup creates a backup successfully | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
@@ -75,3 +94,164 @@ def test_positive_offline_backup(module_target_sat, setup_backup_tests): | |||||||||||||||||||||||||||||||||||||
| # Verify foremanctl is still healthy after backup | ||||||||||||||||||||||||||||||||||||||
| result = module_target_sat.execute('foremanctl health', timeout='5m') | ||||||||||||||||||||||||||||||||||||||
| assert result.status == 0, f'foremanctl health check failed after backup:\n{result.stdout}' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| @pytest.mark.e2e | ||||||||||||||||||||||||||||||||||||||
| def test_positive_backup_restore(module_target_sat, setup_backup_tests, module_synced_repos): | ||||||||||||||||||||||||||||||||||||||
| """Verify foremanctl restore recovers a satellite to its original state from backup | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :id: cb8447fb-b25f-4ec7-b515-8fe7391bd867 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :steps: | ||||||||||||||||||||||||||||||||||||||
| 1. Create a backup using foremanctl backup | ||||||||||||||||||||||||||||||||||||||
| 2. Verify backup contains expected files | ||||||||||||||||||||||||||||||||||||||
| 3. Mutate content: add a new repo and delete the existing custom repo | ||||||||||||||||||||||||||||||||||||||
| 4. Remove pulp artifacts to confirm restore repopulates them | ||||||||||||||||||||||||||||||||||||||
| 5. Run foremanctl restore with --force flag | ||||||||||||||||||||||||||||||||||||||
| 6. Verify restore completes successfully | ||||||||||||||||||||||||||||||||||||||
| 7. Run foremanctl health check | ||||||||||||||||||||||||||||||||||||||
| 8. Verify pre-backup content (custom and RH repos) is restored | ||||||||||||||||||||||||||||||||||||||
| 9. Verify content added after backup is absent | ||||||||||||||||||||||||||||||||||||||
| 10. Verify pulp artifacts were restored | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :expectedresults: | ||||||||||||||||||||||||||||||||||||||
| 1. Backup succeeds and contains expected files | ||||||||||||||||||||||||||||||||||||||
| 2. Restore completes with exit status 0 | ||||||||||||||||||||||||||||||||||||||
| 3. Health check passes after restore | ||||||||||||||||||||||||||||||||||||||
| 4. Deleted content is restored to original state | ||||||||||||||||||||||||||||||||||||||
| 5. Content added after backup is absent | ||||||||||||||||||||||||||||||||||||||
| 6. Pulp artifacts are restored | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :Verifies: SAT-44898 | ||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||
| subdir = f'{BACKUP_DIR}backup-{gen_string("alpha")}' | ||||||||||||||||||||||||||||||||||||||
| backup_dir = _create_backup(module_target_sat, subdir) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| files = module_target_sat.execute(f'ls {backup_dir}').stdout.split('\n') | ||||||||||||||||||||||||||||||||||||||
| files = [i for i in files if i.strip()] | ||||||||||||||||||||||||||||||||||||||
| expected_files = get_exp_files(module_target_sat) | ||||||||||||||||||||||||||||||||||||||
| assert set(files).issuperset(expected_files), ( | ||||||||||||||||||||||||||||||||||||||
| f'Some required backup files are missing. Expected: {expected_files}, Found: {files}' | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| post_backup_repo = module_target_sat.api.Repository( | ||||||||||||||||||||||||||||||||||||||
| url=settings.repos.yum_3.url, product=module_synced_repos['custom'].product | ||||||||||||||||||||||||||||||||||||||
| ).create() | ||||||||||||||||||||||||||||||||||||||
| post_backup_repo.sync() | ||||||||||||||||||||||||||||||||||||||
| post_backup_repo = post_backup_repo.read() | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| deleted_repo_id = module_synced_repos['custom'].id | ||||||||||||||||||||||||||||||||||||||
| deleted_repo_name = module_synced_repos['custom'].name | ||||||||||||||||||||||||||||||||||||||
| module_target_sat.api.Repository(id=deleted_repo_id).delete() | ||||||||||||||||||||||||||||||||||||||
| result = module_target_sat.api.Repository().search( | ||||||||||||||||||||||||||||||||||||||
| query={'search': f'name="{deleted_repo_name}"'} | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| assert len(result) == 0, 'Custom repo should be deleted before restore' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| module_target_sat.execute('rm -rf /var/lib/pulp/media/artifact') | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| result = module_target_sat.execute( | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+151
to
+153
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (testing): Assert that pulp artifacts are actually removed before restore to prove restore repopulates them After the
Suggested change
|
||||||||||||||||||||||||||||||||||||||
| f'foremanctl restore {backup_dir} --force', | ||||||||||||||||||||||||||||||||||||||
| timeout='30m', | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
vijaysawant marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||
| assert result.status == 0, f'foremanctl restore failed:\n{result.stdout}\n{result.stderr}' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| result = module_target_sat.execute('foremanctl health', timeout='5m') | ||||||||||||||||||||||||||||||||||||||
| assert result.status == 0, f'foremanctl health check failed after restore:\n{result.stdout}' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| repo = module_target_sat.api.Repository().search( | ||||||||||||||||||||||||||||||||||||||
| query={'search': f'name="{deleted_repo_name}"'} | ||||||||||||||||||||||||||||||||||||||
| )[0] | ||||||||||||||||||||||||||||||||||||||
| assert repo.id == deleted_repo_id, 'Deleted custom repo should be restored' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| rh_repo = module_target_sat.api.Repository().search( | ||||||||||||||||||||||||||||||||||||||
| query={'search': f'''name="{module_synced_repos['rh'].name}"'''} | ||||||||||||||||||||||||||||||||||||||
| )[0] | ||||||||||||||||||||||||||||||||||||||
| assert rh_repo.id == module_synced_repos['rh'].id | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| result = module_target_sat.api.Repository().search( | ||||||||||||||||||||||||||||||||||||||
| query={'search': f'name="{post_backup_repo.name}"'} | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| assert len(result) == 0, 'Content created after backup should not exist after restore' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| assert ( | ||||||||||||||||||||||||||||||||||||||
| int(module_target_sat.execute('find /var/lib/pulp/media/artifact -type f | wc -l').stdout) | ||||||||||||||||||||||||||||||||||||||
| > 0 | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| def test_positive_restore_validate(module_target_sat, setup_backup_tests): | ||||||||||||||||||||||||||||||||||||||
|
sambible marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||
| """Verify foremanctl restore --validate checks backup integrity without making changes | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :id: b4573263-ce88-4a89-9600-8e8b89aa3d63 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :steps: | ||||||||||||||||||||||||||||||||||||||
| 1. Create a backup using foremanctl backup | ||||||||||||||||||||||||||||||||||||||
| 2. Run foremanctl restore with --validate flag | ||||||||||||||||||||||||||||||||||||||
| 3. Verify validation completes successfully without modifying the system | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :expectedresults: | ||||||||||||||||||||||||||||||||||||||
| 1. Backup succeeds | ||||||||||||||||||||||||||||||||||||||
| 2. Restore --validate exits with status 0 | ||||||||||||||||||||||||||||||||||||||
| 3. No changes are made to the system | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :Verifies: SAT-44898 | ||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||
| subdir = f'{BACKUP_DIR}backup-{gen_string("alpha")}' | ||||||||||||||||||||||||||||||||||||||
| backup_dir = _create_backup(module_target_sat, subdir) | ||||||||||||||||||||||||||||||||||||||
| result = module_target_sat.execute( | ||||||||||||||||||||||||||||||||||||||
| f'foremanctl restore {backup_dir} --validate', | ||||||||||||||||||||||||||||||||||||||
| timeout='5m', | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| assert result.status == 0, ( | ||||||||||||||||||||||||||||||||||||||
| f'foremanctl restore --validate failed:\n{result.stdout}\n{result.stderr}' | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| def test_negative_restore_baddir(module_target_sat, setup_backup_tests): | ||||||||||||||||||||||||||||||||||||||
| """Verify foremanctl restore fails with a non-existing backup directory | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :id: a7b530e6-7496-45b6-ba14-198980dc3ca8 | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :steps: | ||||||||||||||||||||||||||||||||||||||
| 1. Run foremanctl restore with a non-existing backup directory | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :expectedresults: | ||||||||||||||||||||||||||||||||||||||
| 1. Restore command exits with non-zero status | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :Verifies: SAT-44898 | ||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||
| bad_dir = f'{BACKUP_DIR}backup-{gen_string("alpha")}' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| result = module_target_sat.execute( | ||||||||||||||||||||||||||||||||||||||
| f'foremanctl restore {bad_dir} --force', | ||||||||||||||||||||||||||||||||||||||
| timeout='5m', | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| assert result.status != 0, 'foremanctl restore should fail with non-existing backup directory' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| def test_negative_restore_no_force(module_target_sat, setup_backup_tests): | ||||||||||||||||||||||||||||||||||||||
| """Verify foremanctl restore fails without --force on an existing deployment | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :id: ba844ee3-6837-4f8d-b856-3bd8cf5f1d2a | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :steps: | ||||||||||||||||||||||||||||||||||||||
| 1. Create a backup using foremanctl backup | ||||||||||||||||||||||||||||||||||||||
| 2. Run foremanctl restore without --force flag | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :expectedresults: | ||||||||||||||||||||||||||||||||||||||
| 1. Backup succeeds | ||||||||||||||||||||||||||||||||||||||
| 2. Restore command exits with non-zero status due to safety check | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| :Verifies: SAT-44898 | ||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||
| subdir = f'{BACKUP_DIR}backup-{gen_string("alpha")}' | ||||||||||||||||||||||||||||||||||||||
| backup_dir = _create_backup(module_target_sat, subdir) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| result = module_target_sat.execute( | ||||||||||||||||||||||||||||||||||||||
| f'foremanctl restore {backup_dir}', | ||||||||||||||||||||||||||||||||||||||
| timeout='5m', | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
| assert result.status != 0, ( | ||||||||||||||||||||||||||||||||||||||
| 'foremanctl restore should fail without --force on existing deployment' | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.