From 0ca5b406e867b407e8797fb2a4e4156d7abc0011 Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Thu, 24 Oct 2024 15:25:26 -0400 Subject: [PATCH 01/11] [6.15.z] Fix cli yum repo authentication test (#16771) Fix cli yum repo authentication test (#16640) There were multiple levels to this error: * fix parametrization error AttributeError: 'generator' object has no attribute 'copy' * fix assertion * filter invalid parametrizations by adding 'yum_compatible' flag - 'latin-1' codec can't encode characters - Validation failed: Upstream password requires upstream username be set. - Validation failed: Upstream username is too long (maximum is 255 characters) What was sadly not done: * make parametrization ids readable for meanigful debugging (cherry picked from commit 1b4ad6332ce4ec87a2f637467bd61b213295a16c) Co-authored-by: dosas --- robottelo/utils/datafactory.py | 15 ++++++++++++--- tests/foreman/cli/test_repository.py | 21 ++++++++++----------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/robottelo/utils/datafactory.py b/robottelo/utils/datafactory.py index 8a5677b38df..ebc524f95c7 100644 --- a/robottelo/utils/datafactory.py +++ b/robottelo/utils/datafactory.py @@ -477,26 +477,35 @@ def valid_http_credentials(url_encoded=False): 'quote': False, 'http_valid': True, }, - {'login': 'admin', 'pass': '', 'quote': False, 'http_valid': False}, - {'login': '', 'pass': 'mypassword', 'quote': False, 'http_valid': False}, - {'login': '', 'pass': '', 'quote': False, 'http_valid': False}, + {'login': 'admin', 'pass': '', 'quote': False, 'http_valid': False, 'yum_compatible': True}, + { + 'login': '', + 'pass': 'mypassword', + 'quote': False, + 'http_valid': False, + 'yum_compatible': False, + }, + {'login': '', 'pass': '', 'quote': False, 'http_valid': False, 'yum_compatible': True}, { 'login': gen_string('alpha', gen_integer(1, 512)), 'pass': gen_string('alpha'), 'quote': False, 'http_valid': False, + 'yum_compatible': False, }, { 'login': gen_string('alphanumeric', gen_integer(1, 512)), 'pass': gen_string('alphanumeric'), 'quote': False, 'http_valid': False, + 'yum_compatible': False, }, { 'login': gen_string('utf8', gen_integer(1, 50)), 'pass': gen_string('utf8'), 'quote': True, 'http_valid': False, + 'yum_compatible': False, 'encoding': 'utf8', }, ] diff --git a/tests/foreman/cli/test_repository.py b/tests/foreman/cli/test_repository.py index ba5be030231..c0e76745f47 100644 --- a/tests/foreman/cli/test_repository.py +++ b/tests/foreman/cli/test_repository.py @@ -754,16 +754,14 @@ def test_positive_synchronize_auth_yum_repo(self, repo, target_sat): 'repo_options', **parametrized( [ - ( - { - 'content-type': 'yum', - 'url': FAKE_5_YUM_REPO, - 'upstream-username': creds['login'], - 'upstream-password': creds['pass'], - } - for creds in valid_http_credentials() - if not creds['http_valid'] - ) + { + 'content-type': 'yum', + 'url': FAKE_5_YUM_REPO, + 'upstream-username': creds['login'], + 'upstream-password': creds['pass'], + } + for creds in valid_http_credentials() + if not creds['http_valid'] and creds.get('yum_compatible') ] ), indirect=['repo_options'], @@ -785,7 +783,8 @@ def test_negative_synchronize_auth_yum_repo(self, repo, target_sat): response = target_sat.cli.Task.progress( {'id': repo_sync[0]['id']}, return_raw_response=True ) - assert "Error: 401, message='Unauthorized'" in response.stderr[1].decode('utf-8') + + assert "Error: 401, message='Unauthorized'" in response.stderr @pytest.mark.tier2 @pytest.mark.upgrade From 235f594579d1539fcec2777d3eba8f3be4103a4e Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Fri, 25 Oct 2024 08:17:28 -0400 Subject: [PATCH 02/11] [6.15.z] New improvements and fixes to pytest req updates plugin (#16787) New improvements and fixes to pytest req updates plugin (#16692) * New fixes and improvements to pytest req updates plugin * Pre commit fixes * More granular reporting (cherry picked from commit 59f2b4afa45fce37d90ad9ea19912ae37f88cfb7) Co-authored-by: Jitendra Yejare --- pytest_plugins/requirements/req_updater.py | 74 ++++++++++++++++--- .../requirements/update_requirements.py | 36 +++++---- 2 files changed, 87 insertions(+), 23 deletions(-) diff --git a/pytest_plugins/requirements/req_updater.py b/pytest_plugins/requirements/req_updater.py index 37d1aabc573..6cf7b62e5ac 100644 --- a/pytest_plugins/requirements/req_updater.py +++ b/pytest_plugins/requirements/req_updater.py @@ -1,15 +1,23 @@ from functools import cached_property import subprocess +import sys + + +class UsageError(Exception): + """The UsageError raised when the package manager is different from uv or pip""" + + pass class ReqUpdater: # Installed package name as key and its counterpart in requirements file as value package_deviates = { 'Betelgeuse': 'betelgeuse', - 'broker': 'broker[docker]', + 'broker': 'broker[docker,podman,hussh]', 'dynaconf': 'dynaconf[vault]', 'Jinja2': 'jinja2', 'Sphinx': 'sphinx', + 'pyyaml': 'PyYAML', } @cached_property @@ -18,9 +26,9 @@ def installed_packages(self): This also normalizes any package names that deviates in requirements file vs installed names """ - installed_pkges = subprocess.run( - 'pip list --format=freeze', capture_output=True, shell=True - ).stdout.decode() + installer_args = [sys.executable, '-m', 'list', '--format=freeze'] + installer_args[2:2] = self.packagae_manager.split(' ') + installed_pkges = subprocess.run(installer_args, capture_output=True).stdout.decode() for pkg in self.package_deviates: if pkg in installed_pkges: # Replacing the installed package names with their names in requirements file @@ -56,16 +64,62 @@ def opt_deviation(self): """Returns new and updates available packages in requirements-optional file""" return set(self.optional_packages).difference(self.installed_packages) + @cached_property + def packagae_manager(self): + if ( + subprocess.run( + [sys.executable, '-m', 'pip', '--version'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ).returncode + == 0 + ): + _manager = 'pip' + elif ( + subprocess.run( + [sys.executable, '-m', 'uv', '--version'], + stdout=subprocess.DEVNULL, + stderr=subprocess.DEVNULL, + ).returncode + == 0 + ): + _manager = 'uv pip' + else: + raise UsageError( + 'The package manager is not identifiable for performing package updates.' + 'Currently only pip and uv is supported. Please manually update the packages ' + 'and rerun pytest command.' + ) + return _manager + def install_req_deviations(self): """Installs new and updates available packages in requirements file""" if self.req_deviation: - subprocess.run( - f"pip install {' '.join(self.req_deviation)}", shell=True, stdout=subprocess.PIPE - ) + lst_of_reqs = ' '.join(f"'{req}'" for req in self.req_deviation) + if ( + subprocess.run( + f"{self.packagae_manager} install {lst_of_reqs}", + shell=True, + stdout=subprocess.PIPE, + ).returncode + == 0 + ): + print('Mandatory requirements are updated.') + else: + print('ERROR: Some issue occurred with updating the required requirements') def install_opt_deviations(self): """Installs new and updates available packages in requirements-optional file""" if self.opt_deviation: - subprocess.run( - f"pip install {' '.join(self.opt_deviation)}", shell=True, stdout=subprocess.PIPE - ) + lst_of_reqs = ' '.join(f"'{req}'" for req in self.opt_deviation) + if ( + subprocess.run( + f"{self.packagae_manager} install {lst_of_reqs}", + shell=True, + stdout=subprocess.PIPE, + ).returncode + == 0 + ): + print('Optional requirements are updated.') + else: + print('ERROR: Some issue occurred with updating the optional requirements') diff --git a/pytest_plugins/requirements/update_requirements.py b/pytest_plugins/requirements/update_requirements.py index 74494427ce3..7aa7dc080ed 100644 --- a/pytest_plugins/requirements/update_requirements.py +++ b/pytest_plugins/requirements/update_requirements.py @@ -5,6 +5,12 @@ updater = ReqUpdater() +def git_deviation_filter(deviation): + """Packages installed from Git branch and the version cant be compared, so ignore them from reporting""" + git_packages = ['nailgun', 'airgun'] + return all(git_pckg not in deviation for git_pckg in git_packages) + + def pytest_addoption(parser): """Options to allow user to update the requirements""" update_options = { @@ -28,24 +34,28 @@ def pytest_report_header(config): # Following will update the mandatory and optional requirements # pytest tests/foreman --collect-only --update-all-reqs """ - if updater.req_deviation: - print(f"Mandatory Requirements Mismatch: {' '.join(updater.req_deviation)}") - if config.getoption('update_required_reqs') or config.getoption('update_all_reqs'): - updater.install_req_deviations() - print('Mandatory requirements are installed to be up-to-date.') + req_deviations = updater.req_deviation + filtered_req_deviations = list(filter(git_deviation_filter, req_deviations)) + if filtered_req_deviations: + print(f"Mandatory Requirements Mismatch: {' '.join(filtered_req_deviations)}") else: print('Mandatory Requirements are up to date.') - - if updater.opt_deviation: - print(f"Optional Requirements Mismatch: {' '.join(updater.opt_deviation)}") - if config.getoption('update_all_reqs'): - updater.install_opt_deviations() - print('Optional requirements are installed to be up-to-date.') + if req_deviations and ( + config.getoption('update_required_reqs') or config.getoption('update_all_reqs') + ): + updater.install_req_deviations() + + opt_deviations = updater.opt_deviation + filtered_opt_deviations = list(filter(git_deviation_filter, opt_deviations)) + if filtered_opt_deviations: + print(f"Optional Requirements Mismatch: {' '.join(filtered_opt_deviations)}") else: print('Optional Requirements are up to date.') + if opt_deviations and config.getoption('update_all_reqs'): + updater.install_opt_deviations() - if updater.req_deviation or updater.opt_deviation: + if req_deviations or opt_deviations: print( - "To update mismatched requirements, run the pytest command with " + "To update requirements, run the pytest with " "'--update-required-reqs' OR '--update-all-reqs' option." ) From 814804e32fca79a12b3e0e592f3d3930f8991954 Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Mon, 28 Oct 2024 00:00:29 -0400 Subject: [PATCH 03/11] [6.15.z] Bump sphinx-autoapi from 3.3.2 to 3.3.3 (#16806) --- requirements-optional.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-optional.txt b/requirements-optional.txt index 807356e4832..9b89bb2ce90 100644 --- a/requirements-optional.txt +++ b/requirements-optional.txt @@ -6,7 +6,7 @@ ruff==0.6.9 # For generating documentation. sphinx==8.1.3 -sphinx-autoapi==3.3.2 +sphinx-autoapi==3.3.3 # For 'manage' interactive shell manage==0.1.15 From 2fad341c19d079360449f6058fe2cc87804a95f8 Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Thu, 31 Oct 2024 10:28:20 -0400 Subject: [PATCH 04/11] [6.15.z] [pre-commit.ci] pre-commit autoupdate (#16829) --- .pre-commit-config.yaml | 4 ++-- robottelo/utils/io/__init__.py | 9 ++++----- tests/robottelo/test_func_locker.py | 7 +++---- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 90c79eefab7..3d528a007ff 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.6.9 + rev: v0.7.1 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] @@ -28,6 +28,6 @@ repos: types: [text] require_serial: true - repo: https://github.com/gitleaks/gitleaks - rev: v8.20.1 + rev: v8.21.2 hooks: - id: gitleaks diff --git a/robottelo/utils/io/__init__.py b/robottelo/utils/io/__init__.py index ac23b5e83b5..bb7195f8b6e 100644 --- a/robottelo/utils/io/__init__.py +++ b/robottelo/utils/io/__init__.py @@ -18,11 +18,10 @@ def get_local_file_data(path): checksum = hashlib.sha256(file_content).hexdigest() try: - tarobj = tarfile.open(path, mode='r') - host_counts = get_host_counts(tarobj) - tarobj.close() - extractable = True - json_files_parsable = True + with tarfile.open(path, mode='r') as tarobj: + host_counts = get_host_counts(tarobj) + extractable = True + json_files_parsable = True except (tarfile.TarError, json.JSONDecodeError): host_counts = {} extractable = False diff --git a/tests/robottelo/test_func_locker.py b/tests/robottelo/test_func_locker.py index de2ef29aa33..4a4fbbddd0b 100644 --- a/tests/robottelo/test_func_locker.py +++ b/tests/robottelo/test_func_locker.py @@ -28,10 +28,9 @@ class TmpCountFile: def __init__(self): tmp_root_path = Path(func_locker.get_temp_dir()).joinpath(func_locker.TEMP_ROOT_DIR) tmp_root_path.mkdir(parents=True, exist_ok=True) - self.file = tempfile.NamedTemporaryFile(delete=False, suffix='.counter', dir=tmp_root_path) - self.file_name = self.file.name - self.file.write(b'0') - self.file.close() + with tempfile.NamedTemporaryFile(delete=False, suffix='.counter', dir=tmp_root_path) as cf: + cf.write(b'0') + self.file_name = cf.name def read(self): with open(self.file_name) as cf: From 0bc1d4cf0d145f3acf1d731e87090c8520ea993a Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Fri, 1 Nov 2024 00:03:08 -0400 Subject: [PATCH 05/11] [6.15.z] Bump pytest-reportportal from 5.4.4 to 5.4.5 (#16833) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 58b259840b6..fde7fdc0f8a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,7 @@ pytest==8.3.3 pytest-order==1.3.0 pytest-services==2.2.1 pytest-mock==3.14.0 -pytest-reportportal==5.4.4 +pytest-reportportal==5.4.5 pytest-xdist==3.6.1 pytest-fixturecollection==0.1.2 pytest-ibutsu==2.2.4 From 8b85ad98156c843d378c1be19939834766d21a6b Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Mon, 4 Nov 2024 06:18:14 -0500 Subject: [PATCH 06/11] [6.15.z] removing cloned_from_id key from template object (#16847) --- tests/foreman/api/test_provisioningtemplate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/foreman/api/test_provisioningtemplate.py b/tests/foreman/api/test_provisioningtemplate.py index 3a999f8b726..a1c9502ebb9 100644 --- a/tests/foreman/api/test_provisioningtemplate.py +++ b/tests/foreman/api/test_provisioningtemplate.py @@ -187,7 +187,7 @@ def test_positive_end_to_end_crud( # clone template_origin = template.read_json() # remove unique keys - unique_keys = ('updated_at', 'created_at', 'id', 'name') + unique_keys = ('updated_at', 'created_at', 'id', 'name', 'cloned_from_id') template_origin = { key: value for key, value in template_origin.items() if key not in unique_keys } From feea91616b0bf1a546bb788124d2eda76a8208b5 Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Mon, 4 Nov 2024 08:57:48 -0500 Subject: [PATCH 07/11] [6.15.z] Fix Discovery rule tests with teardown (#16849) --- tests/foreman/ui/test_discoveryrule.py | 36 +++++++++++++++++++------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/tests/foreman/ui/test_discoveryrule.py b/tests/foreman/ui/test_discoveryrule.py index a940771505c..aac8f342e24 100644 --- a/tests/foreman/ui/test_discoveryrule.py +++ b/tests/foreman/ui/test_discoveryrule.py @@ -126,7 +126,7 @@ def test_positive_crud_with_non_admin_user( @pytest.mark.tier2 def test_negative_delete_rule_with_non_admin_user( - module_location, module_org, module_target_sat, reader_user + request, module_location, module_org, module_target_sat, reader_user ): """Delete rule with non-admin user by associating discovery_reader role @@ -148,6 +148,15 @@ def test_negative_delete_rule_with_non_admin_user( organization=[module_org], location=[module_location], ).create() + + # teardown + @request.addfinalizer + def _finalize(): + dr = module_target_sat.api.DiscoveryRule().search(query={'search': f'name={rule_name}'}) + if dr: + dr[0].delete() + hg.delete() + with module_target_sat.ui_session( user=reader_user.login, password=reader_user.password ) as session: @@ -160,7 +169,7 @@ def test_negative_delete_rule_with_non_admin_user( @pytest.mark.run_in_one_thread @pytest.mark.tier3 def test_positive_list_host_based_on_rule_search_query( - session, module_org, module_location, module_discovery_env, target_sat + request, session, module_org, module_location, module_discovery_env, target_sat ): """List all the discovered hosts resolved by given rule's search query e.g. all discovered hosts with cpu_count = 2, and list rule's associated @@ -169,7 +178,6 @@ def test_positive_list_host_based_on_rule_search_query( :id: f7473fa2-7349-42d3-9cdb-f74b55d2f440 :steps: - 1. discovered host with cpu_count = 2 2. Define a rule 'rule1' with search query cpu_count = 2 3. Click on 'Discovered Hosts' from rule1 @@ -177,7 +185,6 @@ def test_positive_list_host_based_on_rule_search_query( 5. Click on 'Associated Hosts' from rule1 :expectedresults: - 1. After step 3, the rule's Discovered host should be listed. 2. The rule's Associated Host should be listed. @@ -185,6 +192,7 @@ def test_positive_list_host_based_on_rule_search_query( """ ip_address = gen_ipaddr() cpu_count = gen_integer(2, 10) + rule_name = gen_string('alpha') rule_search = f'cpu_count = {cpu_count}' # any way create a host to be sure that this org has more than one host host = target_sat.api.Host(organization=module_org, location=module_location).create() @@ -199,6 +207,7 @@ def test_positive_list_host_based_on_rule_search_query( architecture=host.architecture, ).create() discovery_rule = target_sat.api.DiscoveryRule( + name=rule_name, hostgroup=host_group, search_=rule_search, organization=[module_org], @@ -208,9 +217,17 @@ def test_positive_list_host_based_on_rule_search_query( discovered_host = target_sat.api_factory.create_discovered_host( ip_address=ip_address, options={'physicalprocessorcount': cpu_count} ) - # create an other discovered host with an other cpu count - target_sat.api_factory.create_discovered_host(options={'physicalprocessorcount': cpu_count + 1}) - provisioned_host_name = f'{host.domain.read().name}' + + # teardown + @request.addfinalizer + def _finalize(): + host.delete() + dr = target_sat.api.DiscoveryRule().search(query={'search': f'name={rule_name}'}) + if dr: + dr[0].delete() + target_sat.api.Host(id=discovered_host['id']).delete() + host_group.delete() + with session: session.organization.select(org_name=module_org.name) session.location.select(loc_name=module_location.name) @@ -228,9 +245,8 @@ def test_positive_list_host_based_on_rule_search_query( host_name = values['table'][0]['Name'] assert values['searchbox'] == f'discovery_rule = "{discovery_rule.name}"' assert len(values['table']) == 1 - assert provisioned_host_name in host_name - values = session.host.get_details(host_name) - assert values['properties']['properties_table']['IP Address'] == ip_address + values = session.host_new.get_details(host_name, widget_names='overview') + assert values['overview']['details']['details']['ipv4_address'] == ip_address @pytest.mark.e2e From b760c7dbf0297a8058078e49eee53f8f5cea7f88 Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Mon, 4 Nov 2024 14:41:58 -0500 Subject: [PATCH 08/11] [6.15.z] [pre-commit.ci] pre-commit autoupdate (#16854) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d528a007ff..05d63cb500b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,7 +12,7 @@ repos: - id: check-yaml - id: debug-statements - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.7.1 + rev: v0.7.2 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] From 4508d87905a0c7eff6961c98ff1a6338411de65f Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Mon, 4 Nov 2024 22:53:22 -0500 Subject: [PATCH 09/11] [6.15.z] Bump productmd from 1.40 to 1.41 (#16858) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fde7fdc0f8a..9603b7776f6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,7 @@ fauxfactory==3.1.1 jinja2==3.1.4 manifester==0.2.8 navmazing==1.2.2 -productmd==1.40 +productmd==1.41 pyotp==2.9.0 python-box==7.2.0 pytest==8.3.3 From cc6e6f2cee55e5d6b828b3e8cdf608b77f9468e2 Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Tue, 5 Nov 2024 04:40:49 -0500 Subject: [PATCH 10/11] [6.15.z] Fix test_positive_mismatched_satellite_fqdn (#16863) --- tests/foreman/destructive/test_installer.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/foreman/destructive/test_installer.py b/tests/foreman/destructive/test_installer.py index 8c61633fc53..46056ad83a5 100644 --- a/tests/foreman/destructive/test_installer.py +++ b/tests/foreman/destructive/test_installer.py @@ -28,10 +28,15 @@ def set_random_fqdn(target_sat): shortname = gen_string('alpha') new_domain = gen_domain() target_sat.execute( - f'echo "search {new_domain}" >> /etc/resolv.conf; hostnamectl set-hostname {shortname}' + 'mv -f /etc/resolv.conf /etc/resolv.conf.bak; ' + f'echo "search {new_domain}" > /etc/resolv.conf; ' + f'hostnamectl set-hostname {shortname}' ) yield shortname, new_domain - target_sat.execute(f'hostnamectl set-hostname {target_sat.hostname}') + target_sat.execute( + 'mv -f /etc/resolv.conf.bak /etc/resolv.conf; ' + f'hostnamectl set-hostname {target_sat.hostname}' + ) def test_installer_sat_pub_directory_accessibility(target_sat): From df130d0883705a73c97fbef49f072ccd9ebe7096 Mon Sep 17 00:00:00 2001 From: Satellite QE <115476073+Satellite-QE@users.noreply.github.com> Date: Tue, 5 Nov 2024 05:54:02 -0500 Subject: [PATCH 11/11] [6.15.z] Refactor IPA users and groups, make the data structure make sense (#16866) --- conf/ipa.yaml.template | 10 ++-- pytest_fixtures/component/satellite_auth.py | 2 +- robottelo/config/validators.py | 6 +- robottelo/hosts.py | 2 +- tests/foreman/ui/test_ldap_authentication.py | 60 +++++++++++--------- 5 files changed, 44 insertions(+), 36 deletions(-) diff --git a/conf/ipa.yaml.template b/conf/ipa.yaml.template index a8a15add1f2..88c13a90c54 100755 --- a/conf/ipa.yaml.template +++ b/conf/ipa.yaml.template @@ -9,10 +9,10 @@ IPA: OTP_USER: otp_user TIME_BASED_SECRET: # update the time based token secret DISABLED_IPA_USER: disabled_user - GROUP_USERS: - - satadmin_01 - - satuser_01 + USERS: + USER: satuser_01 + ADMIN: satadmin_01 GROUPS: - - satadmins - - satusers + USERS: satusers + ADMINS: satadmins KEYTAB_URL: diff --git a/pytest_fixtures/component/satellite_auth.py b/pytest_fixtures/component/satellite_auth.py index ef69fcc822c..9468eba15d1 100644 --- a/pytest_fixtures/component/satellite_auth.py +++ b/pytest_fixtures/component/satellite_auth.py @@ -87,7 +87,7 @@ def ipa_data(): 'ldap_hostname': settings.ipa.hostname, 'time_based_secret': settings.ipa.time_based_secret, 'disabled_user_ipa': settings.ipa.disabled_ipa_user, - 'group_users': settings.ipa.group_users, + 'users': settings.ipa.users, 'groups': settings.ipa.groups, } diff --git a/robottelo/config/validators.py b/robottelo/config/validators.py index 9056b20358a..12c32770cdd 100644 --- a/robottelo/config/validators.py +++ b/robottelo/config/validators.py @@ -172,8 +172,12 @@ 'ipa.user', 'ipa.otp_user', 'ipa.disabled_ipa_user', - 'ipa.group_users', + 'ipa.users', + 'ipa.users.user', + 'ipa.users.admin', 'ipa.groups', + 'ipa.groups.users', + 'ipa.groups.admins', 'ipa.keytab_url', 'ipa.time_based_secret', must_exist=True, diff --git a/robottelo/hosts.py b/robottelo/hosts.py index 65162601161..81aa6fadb96 100644 --- a/robottelo/hosts.py +++ b/robottelo/hosts.py @@ -2652,7 +2652,7 @@ def __init__(self, sat_obj, **kwargs): 'base_dn': settings.ipa.basedn, 'disabled_user_ipa': settings.ipa.disabled_ipa_user, 'group_base_dn': settings.ipa.grpbasedn, - 'group_users': settings.ipa.group_users, + 'users': settings.ipa.users, 'groups': settings.ipa.groups, 'ipa_otp_username': settings.ipa.otp_user, 'ldap_user_cn': settings.ipa.username, diff --git a/tests/foreman/ui/test_ldap_authentication.py b/tests/foreman/ui/test_ldap_authentication.py index 1992c92a618..1339fdda23d 100644 --- a/tests/foreman/ui/test_ldap_authentication.py +++ b/tests/foreman/ui/test_ldap_authentication.py @@ -103,16 +103,6 @@ def rhsso_groups_teardown(default_sso_host): default_sso_host.delete_rhsso_group(group_name) -@pytest.fixture -def multigroup_setting_cleanup(default_ipa_host): - """Adding and removing the user to/from ipa group""" - sat_users = settings.ipa.groups - idm_users = settings.ipa.group_users - default_ipa_host.add_user_to_usergroup(idm_users[1], sat_users[0]) - yield - default_ipa_host.remove_user_from_usergroup(idm_users[1], sat_users[0]) - - @pytest.fixture def ipa_add_user(default_ipa_host): """Create an IPA user and delete it""" @@ -1163,7 +1153,13 @@ def test_login_failure_if_internal_user_exist( @pytest.mark.tier2 def test_userlist_with_external_admin( - session, auth_source_ipa, ldap_tear_down, groups_teardown, target_sat + session, + auth_source_ipa, + ldap_tear_down, + groups_teardown, + target_sat, + module_org, + module_location, ): """All the external users should be displayed to all LDAP admins (internal and external). @@ -1190,8 +1186,10 @@ def test_userlist_with_external_admin( into Satellite as a local or remote admin. """ # step 1, 2, 3 are already done from IDM and gather the data from settings - sat_admins, sat_users = settings.ipa.groups - idm_admin, idm_user = settings.ipa.group_users + idm_groups_users = settings.ipa.groups.users + idm_groups_admins = settings.ipa.groups.admins + idm_users_user = settings.ipa.users.user + idm_users_admin = settings.ipa.users.admin auth_source_name = f'LDAP-{auth_source_ipa.name}' user_permissions = {'Katello::ActivationKey': PERMISSIONS['Katello::ActivationKey']} @@ -1202,7 +1200,7 @@ def test_userlist_with_external_admin( { 'usergroup.name': 'sat_users', 'roles.resources.assigned': [katello_role.name], - 'external_groups.name': sat_users, + 'external_groups.name': idm_groups_users, 'external_groups.auth_source': auth_source_name, } ) @@ -1210,24 +1208,32 @@ def test_userlist_with_external_admin( { 'usergroup.name': 'sat_admins', 'roles.admin': True, - 'external_groups.name': sat_admins, + 'external_groups.name': idm_groups_admins, 'external_groups.auth_source': auth_source_name, } ) - with target_sat.ui_session(user=idm_user, password=settings.server.ssh_password) as ldapsession: - assert idm_user in ldapsession.task.read_all()['current_user'] + # create AK to read a current user in the next session + ak_name = gen_string('alpha') + session.activationkey.create({'name': ak_name}) + with target_sat.ui_session(user=idm_users_user, password=settings.ipa.password) as ldapsession: + current_user = ldapsession.activationkey.read(ak_name, 'current_user')['current_user'] + assert idm_users_user in current_user # verify the users count with local admin and remote/external admin with ( target_sat.ui_session( - user=idm_admin, password=settings.server.ssh_password + user=idm_users_admin, password=settings.ipa.password ) as remote_admin_session, target_sat.ui_session( user=settings.server.admin_username, password=settings.server.admin_password ) as local_admin_session, ): - assert local_admin_session.user.search(idm_user)[0]['Username'] == idm_user - assert remote_admin_session.user.search(idm_user)[0]['Username'] == idm_user + local_admin_session.organization.select(module_org.name) + local_admin_session.location.select(module_location.name) + remote_admin_session.organization.select(module_org.name) + remote_admin_session.location.select(module_location.name) + assert local_admin_session.user.search(idm_users_user)[0]['Username'] == idm_users_user + assert remote_admin_session.user.search(idm_users_user)[0]['Username'] == idm_users_user @pytest.mark.tier2 @@ -1284,7 +1290,6 @@ def test_positive_group_sync_open_ldap_authsource( def test_verify_group_permissions( session, auth_source_ipa, - multigroup_setting_cleanup, groups_teardown, ldap_tear_down, target_sat, @@ -1303,8 +1308,9 @@ def test_verify_group_permissions( :expectedresults: Group with higher permission is applied on the user """ - sat_users = settings.ipa.groups - idm_users = settings.ipa.group_users + idm_groups_users = settings.ipa.groups.users + idm_groups_admins = settings.ipa.groups.admins + idm_users_admin = settings.ipa.users.admin auth_source_name = f'LDAP-{auth_source_ipa.name}' user_permissions = {None: ['access_dashboard']} katello_role = target_sat.api.Role().create() @@ -1314,7 +1320,7 @@ def test_verify_group_permissions( { 'usergroup.name': 'sat_users', 'roles.resources.assigned': [katello_role.name], - 'external_groups.name': sat_users[0], + 'external_groups.name': idm_groups_users, 'external_groups.auth_source': auth_source_name, } ) @@ -1322,14 +1328,12 @@ def test_verify_group_permissions( { 'usergroup.name': 'sat_admins', 'roles.admin': True, - 'external_groups.name': sat_users[1], + 'external_groups.name': idm_groups_admins, 'external_groups.auth_source': auth_source_name, } ) location_name = gen_string('alpha') - with target_sat.ui_session( - user=idm_users[1], password=settings.server.ssh_password - ) as ldapsession: + with target_sat.ui_session(user=idm_users_admin, password=settings.ipa.password) as ldapsession: ldapsession.location.create({'name': location_name}) location = target_sat.api.Location().search(query={'search': f'name="{location_name}"'})[0] assert location.name == location_name