diff --git a/.github/workflows/auto_cherry_pick_merge.yaml b/.github/workflows/auto_cherry_pick_merge.yaml index 924bc9fccfd..0f0e9e33b35 100644 --- a/.github/workflows/auto_cherry_pick_merge.yaml +++ b/.github/workflows/auto_cherry_pick_merge.yaml @@ -40,7 +40,7 @@ jobs: - name: Wait for other status checks to Pass id: waitforstatuschecks - uses: lewagon/wait-on-check-action@v1.3.1 + uses: lewagon/wait-on-check-action@v1.3.3 with: ref: ${{ github.head_ref }} repo-token: ${{ secrets.CHERRYPICK_PAT }} diff --git a/.github/workflows/dependency_merge.yml b/.github/workflows/dependency_merge.yml index be56def8996..90aeb7a9bc6 100644 --- a/.github/workflows/dependency_merge.yml +++ b/.github/workflows/dependency_merge.yml @@ -51,7 +51,7 @@ jobs: - name: Wait for other status checks to Pass id: waitforstatuschecks - uses: lewagon/wait-on-check-action@v1.3.1 + uses: lewagon/wait-on-check-action@v1.3.3 with: ref: ${{ github.head_ref }} repo-token: ${{ secrets.CHERRYPICK_PAT }} diff --git a/pytest_fixtures/component/repository.py b/pytest_fixtures/component/repository.py index fd9ba01b88e..6a1c43af100 100644 --- a/pytest_fixtures/component/repository.py +++ b/pytest_fixtures/component/repository.py @@ -4,7 +4,8 @@ from nailgun.entity_mixins import call_entity_method_with_timeout import pytest -from robottelo.constants import DEFAULT_ARCHITECTURE, PRDS, REPOS, REPOSET +from robottelo.config import settings +from robottelo.constants import DEFAULT_ARCHITECTURE, DEFAULT_ORG, PRDS, REPOS, REPOSET @pytest.fixture(scope='module') @@ -102,6 +103,16 @@ def module_repository(os_path, module_product, module_target_sat): return repo +@pytest.fixture +def custom_synced_repo(target_sat): + custom_repo = target_sat.api.Repository( + product=target_sat.api.Product(organization=DEFAULT_ORG).create(), + url=settings.repos.yum_0.url, + ).create() + custom_repo.sync() + return custom_repo + + def _simplify_repos(request, repos): """This is a helper function that transforms repos_collection related fixture parameters into a list that can be passed to robottelo.host_helpers.RepositoryMixins.RepositoryCollection diff --git a/requirements.txt b/requirements.txt index 8737facd924..2cbd392b9b2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # Version updates managed by dependabot -betelgeuse==1.10.0 +betelgeuse==1.11.0 broker[docker]==0.4.1 cryptography==41.0.7 deepdiff==6.7.1 diff --git a/robottelo/host_helpers/cli_factory.py b/robottelo/host_helpers/cli_factory.py index 3a4fd4e627c..7ff8eb086ef 100644 --- a/robottelo/host_helpers/cli_factory.py +++ b/robottelo/host_helpers/cli_factory.py @@ -691,7 +691,7 @@ def _setup_org_for_a_rh_repo(self, options=None): 1. Checks if organization and lifecycle environment were given, otherwise creates new ones. - 2. Clones and uploads manifest. + 2. If manifest does not exist, clone and upload it. 3. Enables RH repo and synchronizes it. 4. Checks if content view was given, otherwise creates a new one and - adds the RH repo @@ -717,15 +717,13 @@ def _setup_org_for_a_rh_repo(self, options=None): env_id = self.make_lifecycle_environment({'organization-id': org_id})['id'] else: env_id = options['lifecycle-environment-id'] - # Clone manifest and upload it - with clone() as manifest: - self._satellite.put(manifest.path, manifest.name) - try: - self._satellite.cli.Subscription.upload( - {'file': manifest.name, 'organization-id': org_id} - ) - except CLIReturnCodeError as err: - raise CLIFactoryError(f'Failed to upload manifest\n{err.msg}') + # If manifest does not exist, clone and upload it + if len(self._satellite.cli.Subscription.exists({'organization-id': org_id})) == 0: + with clone() as manifest: + try: + self._satellite.upload_manifest(org_id, manifest.content) + except CLIReturnCodeError as err: + raise CLIFactoryError(f'Failed to upload manifest\n{err.msg}') # Enable repo from Repository Set try: self._satellite.cli.RepositorySet.enable( @@ -820,6 +818,11 @@ def _setup_org_for_a_rh_repo(self, options=None): ), } ) + # Override RHST product to true ( turned off by default in 6.14 ) + rhel_repo = self._satellite.cli.Repository.info({'id': rhel_repo['id']}) + self._satellite.cli.ActivationKey.content_override( + {'id': activationkey_id, 'content-label': rhel_repo['content-label'], 'value': 'true'} + ) return { 'activationkey-id': activationkey_id, 'content-view-id': cv_id, diff --git a/scripts/polarion-test-case-upload.sh b/scripts/polarion-test-case-upload.sh index 987a77d6466..888bacb04f0 100755 --- a/scripts/polarion-test-case-upload.sh +++ b/scripts/polarion-test-case-upload.sh @@ -74,6 +74,7 @@ TRANSFORM_CUSTOMERSCENARIO_VALUE = default_config._transform_to_lower DEFAULT_CUSTOMERSCENARIO_VALUE = 'false' DEFAULT_REQUIREMENT_TEAM_VALUE = None TRANSFORM_REQUIREMENT_TEAM_VALUE = default_config._transform_to_lower +MARKERS_IGNORE_LIST = ['parametrize', 'skip.*', 'usefixtures', 'rhel_ver_.*'] EOF set -x diff --git a/tests/foreman/api/test_audit.py b/tests/foreman/api/test_audit.py index 1eff8e5e599..85bcec9bd70 100644 --- a/tests/foreman/api/test_audit.py +++ b/tests/foreman/api/test_audit.py @@ -1,6 +1,6 @@ """Tests for audit functionality. -:Requirement: Audit +:Requirement: AuditLog :CaseAutomation: Automated diff --git a/tests/foreman/api/test_discoveryrule.py b/tests/foreman/api/test_discoveryrule.py index 9420c01cf84..6bdde9728b5 100644 --- a/tests/foreman/api/test_discoveryrule.py +++ b/tests/foreman/api/test_discoveryrule.py @@ -165,7 +165,7 @@ def test_positive_update_and_provision_with_rule_priority( @pytest.mark.tier3 def test_positive_multi_provision_with_rule_limit( - module_target_sat, module_discovery_hostgroup, discovery_location, discovery_org + request, module_target_sat, module_discovery_hostgroup, discovery_location, discovery_org ): """Create a discovery rule with certain host limit and try to provision more than the passed limit @@ -177,13 +177,12 @@ def test_positive_multi_provision_with_rule_limit( :CaseImportance: High """ - for _ in range(2): - discovered_host = module_target_sat.api_factory.create_discovered_host() - + discovered_host1 = module_target_sat.api_factory.create_discovered_host() + discovered_host2 = module_target_sat.api_factory.create_discovered_host() rule = module_target_sat.api.DiscoveryRule( max_count=1, hostgroup=module_discovery_hostgroup, - search_=f'name = {discovered_host["name"]}', + search_=f'name = {discovered_host1["name"]}', location=[discovery_location], organization=[discovery_org], priority=1000, @@ -192,6 +191,10 @@ def test_positive_multi_provision_with_rule_limit( assert '1 discovered hosts were provisioned' in result['message'] # Delete discovery rule - rule.delete() - with pytest.raises(HTTPError): - rule.read() + @request.addfinalizer + def _finalize(): + rule.delete() + module_target_sat.api.Host(id=discovered_host1['id']).delete() + module_target_sat.api.DiscoveredHost(id=discovered_host2['id']).delete() + with pytest.raises(HTTPError): + rule.read() diff --git a/tests/foreman/api/test_provisioning.py b/tests/foreman/api/test_provisioning.py index 67c410cc2e7..78e66672b6d 100644 --- a/tests/foreman/api/test_provisioning.py +++ b/tests/foreman/api/test_provisioning.py @@ -65,6 +65,7 @@ def assert_host_logs(channel, pattern): @pytest.mark.e2e +@pytest.mark.upgrade @pytest.mark.parametrize('pxe_loader', ['bios', 'uefi'], indirect=True) @pytest.mark.on_premises_provisioning @pytest.mark.rhel_ver_match('[^6]') @@ -185,12 +186,18 @@ def test_rhel_pxe_provisioning( ) assert job['result'] == 'success', 'Job invocation failed' + # check if katello-ca-consumer is not used while host registration + assert provisioning_host.execute('rpm -qa |grep katello-ca-consumer').status == 1 + assert ( + 'katello-ca-consumer' not in provisioning_host.execute('cat /root/install.post.log').stdout + ) # assert that the host is subscribed and consumes # subsctiption provided by the activation key assert provisioning_host.subscribed, 'Host is not subscribed' @pytest.mark.e2e +@pytest.mark.upgrade @pytest.mark.parametrize('pxe_loader', ['ipxe'], indirect=True) @pytest.mark.on_premises_provisioning @pytest.mark.rhel_ver_match('[^6]') @@ -320,6 +327,7 @@ def test_rhel_ipxe_provisioning( @pytest.mark.skip_if_open("BZ:2242925") @pytest.mark.e2e +@pytest.mark.upgrade @pytest.mark.parametrize('pxe_loader', ['http_uefi'], indirect=True) @pytest.mark.on_premises_provisioning @pytest.mark.rhel_ver_match('[^6]') @@ -581,7 +589,6 @@ def test_rhel_pxe_provisioning_fips_enabled( # subsctiption provided by the activation key assert provisioning_host.subscribed, 'Host is not subscribed' - @pytest.mark.e2e @pytest.mark.parametrize('pxe_loader', ['bios', 'uefi'], indirect=True) @pytest.mark.parametrize('capsule_provisioning_rhel_content', [8], indirect=True) @@ -705,3 +712,24 @@ def test_capsule_pxe_provisioning( # assert that the host is subscribed and consumes # subsctiption provided by the activation key assert provisioning_host.subscribed, 'Host is not subscribed' + + +@pytest.mark.stubbed +def test_rhel_provisioning_using_realm(): + """Provision a host using realm + + :id: 687e7d71-7e46-46d5-939b-4562f88c4598 + + :steps: + 1. Configure satellite for provisioning + 2. Configure Satellite for Realm support + 3. Provision a Host + 4. Check host is subscribed to Satellite + + :expectedresults: + 1. Provisioning via Realm is successful + 2. Check if the provisioned host is automatically registered to IdM + 3. Host installs right version of RHEL + 4. Satellite is able to run REX job on the host + 5. Host is registered to Satellite and subscription status is 'Success' + """ diff --git a/tests/foreman/api/test_provisioningtemplate.py b/tests/foreman/api/test_provisioningtemplate.py index ba0574489b9..b154eaa4e8b 100644 --- a/tests/foreman/api/test_provisioningtemplate.py +++ b/tests/foreman/api/test_provisioningtemplate.py @@ -581,7 +581,7 @@ def test_positive_template_check_rex_snippet( :steps: 1. Create a host by setting host params remote_execution_ssh_user, remote_execution_create_user, remote_execution_effective_user_method and remote_execution_ssh_keys - 2. Read the provision templete to verify host params + 2. Read the provision template to verify host params :expectedresults: The rendered template has the host params set and correct home directory permissions for the rex user. @@ -641,6 +641,67 @@ def test_positive_template_check_rex_snippet( ) assert ssh_key in rex_snippet + @pytest.mark.parametrize('module_sync_kickstart_content', [7, 8, 9], indirect=True) + def test_positive_template_check_rex_pull_mode_snippet( + self, + module_sync_kickstart_content, + module_target_sat, + module_provisioning_capsule, + module_sca_manifest_org, + module_location, + module_default_org_view, + module_lce_library, + default_architecture, + default_partitiontable, + ): + """Read the provision template and verify the host params and REX pull mode snippet rendered correctly. + + :id: e5212c46-d269-4bce-8e03-9d00c086e69m + + :steps: + 1. Create a host by setting host param enable-remote-execution-pull/host_registration_remote_execution_pull + 2. Read the template to verify the host param and REX pull mode snippet for respective rhel hosts + + :expectedresults: The rendered template has the host params set and correct home directory permissions for the rex user + + :parametrized: yes + """ + host = module_target_sat.api.Host( + organization=module_sca_manifest_org, + location=module_location, + name=gen_string('alpha').lower(), + mac=gen_mac(multicast=False), + operatingsystem=module_sync_kickstart_content.os, + architecture=default_architecture, + domain=module_sync_kickstart_content.domain, + root_pass=settings.provisioning.host_root_password, + ptable=default_partitiontable, + host_parameters_attributes=[ + { + 'name': 'host_registration_remote_execution_pull', + 'value': True, + 'parameter_type': 'boolean', + }, + { + 'name': 'enable-remote-execution-pull', + 'value': True, + 'parameter_type': 'boolean', + }, + ], + ).create() + rex_snippet = host.read_template(data={'template_kind': 'provision'})['template'] + assert 'chmod +x /root/remote_execution_pull_setup.sh' in rex_snippet + + rex_snippet = host.read_template(data={'template_kind': 'host_init_config'})['template'] + assert 'Starting deployment of REX pull provider' in rex_snippet + pkg_manager = 'yum' if module_sync_kickstart_content.rhel_ver < 8 else 'dnf' + assert f'{pkg_manager} -y install foreman_ygg_worker' in rex_snippet + assert 'broker = ["mqtts://$SERVER_NAME:1883"]' in rex_snippet + assert 'systemctl try-restart yggdrasild' in rex_snippet + assert 'systemctl enable --now yggdrasild' in rex_snippet + assert 'yggdrasil status' in rex_snippet + assert 'Remote execution pull provider successfully configured!' in rex_snippet + @pytest.mark.parametrize('module_sync_kickstart_content', [7, 8, 9], indirect=True) def test_positive_template_check_fips_enabled( self, diff --git a/tests/foreman/api/test_registration.py b/tests/foreman/api/test_registration.py index dab85fa6209..77fd856db11 100644 --- a/tests/foreman/api/test_registration.py +++ b/tests/foreman/api/test_registration.py @@ -20,6 +20,7 @@ from fauxfactory import gen_ipaddr, gen_mac import pytest +from requests import HTTPError from robottelo import constants from robottelo.config import settings @@ -213,3 +214,16 @@ def test_positive_rex_interface_for_global_registration( assert interface['execution'] is True assert interface['ip'] == ip assert interface['mac'] == mac_address + + +@pytest.mark.tier1 +def test_negative_global_registration_without_ak(module_target_sat): + """Attempt to register a host without ActivationKey + + :id: e48a6260-97e0-4234-a69c-77bbbcde85de + + :expectedresults: Generate command is disabled without ActivationKey + """ + with pytest.raises(HTTPError) as context: + module_target_sat.api.RegistrationCommand().create() + assert 'Missing activation key!' in context.value.response.text diff --git a/tests/foreman/api/test_role.py b/tests/foreman/api/test_role.py index df0bc677718..da880c71f59 100644 --- a/tests/foreman/api/test_role.py +++ b/tests/foreman/api/test_role.py @@ -587,7 +587,7 @@ def test_negative_access_entities_from_org_admin( sc = self.user_config(user, target_sat) # Getting the domain from user with pytest.raises(HTTPError): - target_sat.api.Domain(sc, id=domain.id).read() + target_sat.api.Domain(server_config=sc, id=domain.id).read() @pytest.mark.tier3 def test_negative_access_entities_from_user( @@ -620,7 +620,7 @@ def test_negative_access_entities_from_user( sc = self.user_config(user, target_sat) # Getting the domain from user with pytest.raises(HTTPError): - target_sat.api.Domain(sc, id=domain.id).read() + target_sat.api.Domain(server_config=sc, id=domain.id).read() @pytest.mark.tier2 def test_positive_override_cloned_role_filter(self, role_taxonomies, target_sat): @@ -1018,13 +1018,13 @@ def test_positive_user_group_users_access_as_org_admin(self, role_taxonomies, ta auth=(login, password), url=target_sat.url, verify=settings.server.verify_ca ) try: - target_sat.api.Domain(sc).search( + target_sat.api.Domain(server_config=sc).search( query={ 'organization-id': role_taxonomies['org'].id, 'location-id': role_taxonomies['loc'].id, } ) - target_sat.api.Subnet(sc).search( + target_sat.api.Subnet(server_config=sc).search( query={ 'organization-id': role_taxonomies['org'].id, 'location-id': role_taxonomies['loc'].id, @@ -1032,8 +1032,8 @@ def test_positive_user_group_users_access_as_org_admin(self, role_taxonomies, ta ) except HTTPError as err: pytest.fail(str(err)) - assert domain.id in [dom.id for dom in target_sat.api.Domain(sc).search()] - assert subnet.id in [sub.id for sub in target_sat.api.Subnet(sc).search()] + assert domain.id in [dom.id for dom in target_sat.api.Domain(server_config=sc).search()] + assert subnet.id in [sub.id for sub in target_sat.api.Subnet(server_config=sc).search()] @pytest.mark.tier3 def test_positive_user_group_users_access_contradict_as_org_admins(self): @@ -1098,7 +1098,7 @@ def test_negative_assign_org_admin_to_user_group( for user in [user_one, user_two]: sc = self.user_config(user, target_sat) with pytest.raises(HTTPError): - target_sat.api.Domain(sc, id=dom.id).read() + target_sat.api.Domain(server_config=sc, id=dom.id).read() @pytest.mark.tier2 def test_negative_assign_taxonomies_by_org_admin( @@ -1149,7 +1149,7 @@ def test_negative_assign_taxonomies_by_org_admin( auth=(user_login, user_pass), url=target_sat.url, verify=settings.server.verify_ca ) # Getting the domain from user1 - dom = target_sat.api.Domain(sc, id=dom.id).read() + dom = target_sat.api.Domain(server_config=sc, id=dom.id).read() dom.organization = [filter_taxonomies['org']] with pytest.raises(HTTPError): dom.update(['organization']) @@ -1319,7 +1319,7 @@ def test_negative_create_roles_by_org_admin(self, role_taxonomies, target_sat): role_name = gen_string('alpha') with pytest.raises(HTTPError): target_sat.api.Role( - sc, + server_config=sc, name=role_name, organization=[role_taxonomies['org']], location=[role_taxonomies['loc']], @@ -1346,7 +1346,7 @@ def test_negative_modify_roles_by_org_admin(self, role_taxonomies, target_sat): ) test_role = target_sat.api.Role().create() sc = self.user_config(user, target_sat) - test_role = target_sat.api.Role(sc, id=test_role.id).read() + test_role = target_sat.api.Role(server_config=sc, id=test_role.id).read() test_role.organization = [role_taxonomies['org']] test_role.location = [role_taxonomies['loc']] with pytest.raises(HTTPError): @@ -1386,7 +1386,7 @@ def test_negative_admin_permissions_to_org_admin(self, role_taxonomies, target_s auth=(user_login, user_pass), url=target_sat.url, verify=settings.server.verify_ca ) with pytest.raises(HTTPError): - target_sat.api.User(sc, id=1).read() + target_sat.api.User(server_config=sc, id=1).read() @pytest.mark.tier2 @pytest.mark.upgrade @@ -1435,7 +1435,7 @@ def test_positive_create_user_by_org_admin(self, role_taxonomies, target_sat): user_login = gen_string('alpha') user_pass = gen_string('alphanumeric') user = target_sat.api.User( - sc_user, + server_config=sc_user, login=user_login, password=user_pass, role=[org_admin.id], @@ -1476,7 +1476,7 @@ def test_positive_access_users_inside_org_admin_taxonomies(self, role_taxonomies test_user = self.create_simple_user(filter_taxos=role_taxonomies) sc = self.user_config(user, target_sat) try: - target_sat.api.User(sc, id=test_user.id).read() + target_sat.api.User(server_config=sc, id=test_user.id).read() except HTTPError as err: pytest.fail(str(err)) @@ -1518,7 +1518,9 @@ def test_positive_create_nested_location(self, role_taxonomies, target_sat): auth=(user_login, user_pass), url=target_sat.url, verify=settings.server.verify_ca ) name = gen_string('alphanumeric') - location = target_sat.api.Location(sc, name=name, parent=role_taxonomies['loc'].id).create() + location = target_sat.api.Location( + server_config=sc, name=name, parent=role_taxonomies['loc'].id + ).create() assert location.name == name @pytest.mark.tier2 @@ -1550,7 +1552,7 @@ def test_negative_access_users_outside_org_admin_taxonomies( test_user = self.create_simple_user(filter_taxos=filter_taxonomies) sc = self.user_config(user, target_sat) with pytest.raises(HTTPError): - target_sat.api.User(sc, id=test_user.id).read() + target_sat.api.User(server_config=sc, id=test_user.id).read() @pytest.mark.tier1 def test_negative_create_taxonomies_by_org_admin(self, role_taxonomies, target_sat): @@ -1586,11 +1588,11 @@ def test_negative_create_taxonomies_by_org_admin(self, role_taxonomies, target_s auth=(user_login, user_pass), url=target_sat.url, verify=settings.server.verify_ca ) with pytest.raises(HTTPError): - target_sat.api.Organization(sc, name=gen_string('alpha')).create() + target_sat.api.Organization(server_config=sc, name=gen_string('alpha')).create() if not is_open("BZ:1825698"): try: loc_name = gen_string('alpha') - loc = target_sat.api.Location(sc, name=loc_name).create() + loc = target_sat.api.Location(server_config=sc, name=loc_name).create() except HTTPError as err: pytest.fail(str(err)) assert loc_name == loc.name @@ -1643,7 +1645,7 @@ def test_positive_access_all_global_entities_by_org_admin( target_sat.api.Errata, target_sat.api.OperatingSystem, ]: - entity(sc).search() + entity(server_config=sc).search() except HTTPError as err: pytest.fail(str(err)) @@ -1684,7 +1686,7 @@ def test_negative_access_entities_from_ldap_org_admin( verify=settings.server.verify_ca, ) with pytest.raises(HTTPError): - target_sat.api.Architecture(sc).search() + target_sat.api.Architecture(server_config=sc).search() user = target_sat.api.User().search( query={'search': f"login={create_ldap['ldap_user_name']}"} )[0] @@ -1692,7 +1694,7 @@ def test_negative_access_entities_from_ldap_org_admin( user.update(['role']) # Trying to access the domain resource created in org admin role with pytest.raises(HTTPError): - target_sat.api.Domain(sc, id=domain.id).read() + target_sat.api.Domain(server_config=sc, id=domain.id).read() @pytest.mark.tier3 def test_negative_access_entities_from_ldap_user( @@ -1729,7 +1731,7 @@ def test_negative_access_entities_from_ldap_user( verify=settings.server.verify_ca, ) with pytest.raises(HTTPError): - target_sat.api.Architecture(sc).search() + target_sat.api.Architecture(server_config=sc).search() user = target_sat.api.User().search( query={'search': f"login={create_ldap['ldap_user_name']}"} )[0] @@ -1737,7 +1739,7 @@ def test_negative_access_entities_from_ldap_user( user.update(['role']) # Trying to access the Domain resource with pytest.raises(HTTPError): - target_sat.api.Domain(sc, id=domain.id).read() + target_sat.api.Domain(server_config=sc, id=domain.id).read() @pytest.mark.tier3 def test_positive_assign_org_admin_to_ldap_user_group( @@ -1800,7 +1802,7 @@ def test_positive_assign_org_admin_to_ldap_user_group( verify=settings.server.verify_ca, ) # Accessing the Domain resource - target_sat.api.Domain(sc, id=domain.id).read() + target_sat.api.Domain(server_config=sc, id=domain.id).read() @pytest.mark.tier3 def test_negative_assign_org_admin_to_ldap_user_group( @@ -1861,7 +1863,7 @@ def test_negative_assign_org_admin_to_ldap_user_group( ) # Trying to access the Domain resource with pytest.raises(HTTPError): - target_sat.api.Domain(sc, id=domain.id).read() + target_sat.api.Domain(server_config=sc, id=domain.id).read() class TestRoleSearchFilter: diff --git a/tests/foreman/api/test_user.py b/tests/foreman/api/test_user.py index 29442aa3080..de78386805e 100644 --- a/tests/foreman/api/test_user.py +++ b/tests/foreman/api/test_user.py @@ -420,8 +420,12 @@ def test_positive_table_preferences(self, module_target_sat): sc = ServerConfig( auth=(user.login, password), url=module_target_sat.url, verify=settings.server.verify_ca ) - module_target_sat.api.TablePreferences(sc, user=user, name=name, columns=columns).create() - table_preferences = module_target_sat.api.TablePreferences(sc, user=user).search() + module_target_sat.api.TablePreferences( + server_config=sc, user=user, name=name, columns=columns + ).create() + table_preferences = module_target_sat.api.TablePreferences( + server_config=sc, user=user + ).search() assert len(table_preferences) == 1 tp = table_preferences[0] assert hasattr(tp, 'name') @@ -732,7 +736,7 @@ def test_positive_ad_basic_no_roles(self, create_ldap, target_sat): verify=settings.server.verify_ca, ) with pytest.raises(HTTPError): - target_sat.api.Architecture(sc).search() + target_sat.api.Architecture(server_config=sc).search() @pytest.mark.tier3 @pytest.mark.upgrade @@ -783,7 +787,7 @@ def test_positive_access_entities_from_ldap_org_admin(self, create_ldap, module_ verify=settings.server.verify_ca, ) with pytest.raises(HTTPError): - module_target_sat.api.Architecture(sc).search() + module_target_sat.api.Architecture(server_config=sc).search() user = module_target_sat.api.User().search( query={'search': 'login={}'.format(create_ldap['ldap_user_name'])} )[0] @@ -800,7 +804,7 @@ def test_positive_access_entities_from_ldap_org_admin(self, create_ldap, module_ module_target_sat.api.Errata, module_target_sat.api.OperatingSystem, ]: - entity(sc).search() + entity(server_config=sc).search() @pytest.mark.run_in_one_thread @@ -865,7 +869,7 @@ def test_positive_ipa_basic_no_roles(self, create_ldap, target_sat): verify=settings.server.verify_ca, ) with pytest.raises(HTTPError): - target_sat.api.Architecture(sc).search() + target_sat.api.Architecture(server_config=sc).search() @pytest.mark.tier3 @pytest.mark.upgrade @@ -906,7 +910,7 @@ def test_positive_access_entities_from_ipa_org_admin(self, create_ldap, target_s verify=settings.server.verify_ca, ) with pytest.raises(HTTPError): - target_sat.api.Architecture(sc).search() + target_sat.api.Architecture(server_config=sc).search() user = target_sat.api.User().search( query={'search': 'login={}'.format(create_ldap['username'])} )[0] @@ -923,7 +927,7 @@ def test_positive_access_entities_from_ipa_org_admin(self, create_ldap, target_s target_sat.api.Errata, target_sat.api.OperatingSystem, ]: - entity(sc).search() + entity(server_config=sc).search() class TestPersonalAccessToken: diff --git a/tests/foreman/cli/test_errata.py b/tests/foreman/cli/test_errata.py index 0b4b3a37f5c..d7a90b34c58 100644 --- a/tests/foreman/cli/test_errata.py +++ b/tests/foreman/cli/test_errata.py @@ -134,16 +134,14 @@ def products_with_repos(orgs, module_target_sat): @pytest.fixture(scope='module') -def rh_repo( - module_entitlement_manifest_org, module_lce, module_cv, module_ak_cv_lce, module_target_sat -): +def rh_repo(module_sca_manifest_org, module_lce, module_cv, module_ak_cv_lce, module_target_sat): """Add a subscription for the Satellite Tools repo to activation key.""" module_target_sat.cli_factory.setup_org_for_a_rh_repo( { 'product': PRDS['rhel'], 'repository-set': REPOSET['rhst7'], 'repository': REPOS['rhst7']['name'], - 'organization-id': module_entitlement_manifest_org.id, + 'organization-id': module_sca_manifest_org.id, 'content-view-id': module_cv.id, 'lifecycle-environment-id': module_lce.id, 'activationkey-id': module_ak_cv_lce.id, @@ -153,13 +151,13 @@ def rh_repo( @pytest.fixture(scope='module') def custom_repo( - module_entitlement_manifest_org, module_lce, module_cv, module_ak_cv_lce, module_target_sat + module_sca_manifest_org, module_lce, module_cv, module_ak_cv_lce, module_target_sat ): """Create custom repo and add a subscription to activation key.""" module_target_sat.cli_factory.setup_org_for_a_custom_repo( { 'url': REPO_WITH_ERRATA['url'], - 'organization-id': module_entitlement_manifest_org.id, + 'organization-id': module_sca_manifest_org.id, 'content-view-id': module_cv.id, 'lifecycle-environment-id': module_lce.id, 'activationkey-id': module_ak_cv_lce.id, @@ -377,7 +375,7 @@ def filter_sort_errata(sat, org, sort_by_date='issued', filter_by_org=None): # Build a sorted errata info list, which also contains the sort field. errata_internal_ids = [errata['id'] for errata in errata_list] sorted_errata_info = get_sorted_errata_info_by_id( - errata_internal_ids, sort_by=sort_by_date, sort_reversed=sort_reversed + sat, errata_internal_ids, sort_by=sort_by_date, sort_reversed=sort_reversed ) sort_field_values = [errata[sort_by_date] for errata in sorted_errata_info] @@ -491,70 +489,11 @@ def test_positive_install_by_host_collection_and_org( @pytest.mark.tier3 -def test_negative_install_by_hc_id_without_errata_info( - module_entitlement_manifest_org, host_collection, errata_hosts, target_sat -): - """Attempt to install an erratum on a host collection by host collection id but no errata info - specified. - - :id: 3635698d-4f09-4a60-91ea-1957e5949750 - - :Setup: Errata synced on satellite server. - - :Steps: host-collection erratum install --id --organization-id - - - :expectedresults: Error message thrown. - - :CaseImportance: Low - - :CaseLevel: System - """ - with pytest.raises(CLIReturnCodeError, match="Error: Option '--errata' is required"): - target_sat.cli.HostCollection.erratum_install( - { - 'id': host_collection['id'], - 'organization-id': module_entitlement_manifest_org.id, - } - ) - - -@pytest.mark.tier3 -def test_negative_install_by_hc_name_without_errata_info( - module_entitlement_manifest_org, host_collection, errata_hosts, target_sat -): - """Attempt to install an erratum on a host collection by host collection name but no errata - info specified. - - :id: 12d78bca-efd1-407a-9bd3-f989c2bda6a8 - - :Setup: Errata synced on satellite server. - - :Steps: host-collection erratum install --name --organization-id - - - :expectedresults: Error message thrown. - - :CaseImportance: Low - - :CaseLevel: System - """ - with pytest.raises(CLIReturnCodeError, match="Error: Option '--errata' is required"): - target_sat.cli.HostCollection.erratum_install( - { - 'name': host_collection['name'], - 'organization-id': module_entitlement_manifest_org.id, - } - ) - - -@pytest.mark.tier3 -def test_negative_install_without_hc_info( +def test_negative_install_erratum_on_host_collection( module_entitlement_manifest_org, host_collection, module_target_sat ): - """Attempt to install an erratum on a host collection without specifying host collection info. - This test only works with two or more host collections (BZ#1928281). - We have the one from the fixture, just need to create one more at the start of the test. + """Attempt to install an erratum on a host collection + This functionality was removed with katello-agent :id: 753d36f0-d19b-494d-a247-ce2d61c4cf74 @@ -563,9 +502,7 @@ def test_negative_install_without_hc_info( :Steps: host-collection erratum install --errata --organization-id - :expectedresults: Error message thrown. - - :BZ: 1928281 + :expectedresults: Error message thrown. Not supported. Use the remote execution equivalent :CaseImportance: Low @@ -574,63 +511,14 @@ def test_negative_install_without_hc_info( module_target_sat.cli_factory.make_host_collection( {'organization-id': module_entitlement_manifest_org.id} ) - with pytest.raises(CLIReturnCodeError): + with pytest.raises(CLIReturnCodeError) as error: module_target_sat.cli.HostCollection.erratum_install( { 'organization-id': module_entitlement_manifest_org.id, 'errata': [REPO_WITH_ERRATA['errata'][0]['id']], } ) - - -@pytest.mark.tier3 -def test_negative_install_by_hc_id_without_org_info( - module_entitlement_manifest_org, host_collection, module_target_sat -): - """Attempt to install an erratum on a host collection by host collection id but without - specifying any org info. - - :id: b7d32bb3-9c5f-452b-b421-f8e9976ca52c - - :Setup: Errata synced on satellite server. - - :Steps: host-collection erratum install --errata --id - - :expectedresults: Error message thrown. - - :CaseImportance: Low - - :CaseLevel: System - """ - with pytest.raises(CLIReturnCodeError, match='Error: Could not find organization'): - module_target_sat.cli.HostCollection.erratum_install( - {'id': host_collection['id'], 'errata': [REPO_WITH_ERRATA['errata'][0]['id']]} - ) - - -@pytest.mark.tier3 -def test_negative_install_by_hc_name_without_org_info( - module_entitlement_manifest_org, host_collection, module_target_sat -): - """Attempt to install an erratum on a host collection by host collection name but without - specifying any org info. - - :id: 991f5b61-a4d1-444c-8a21-8ffe48e83f76 - - :Setup: Errata synced on satellite server. - - :Steps: host-collection erratum install --errata --name - - :expectedresults: Error message thrown. - - :CaseImportance: Low - - :CaseLevel: System - """ - with pytest.raises(CLIReturnCodeError, match='Error: Could not find organization'): - module_target_sat.cli.HostCollection.erratum_install( - {'name': host_collection['name'], 'errata': [REPO_WITH_ERRATA['errata'][0]['id']]} - ) + assert 'Not supported. Use the remote execution equivalent' in error.value.stderr @pytest.mark.tier3 @@ -1043,7 +931,7 @@ def cleanup(): ids=('org_id', 'org_name', 'org_label', 'no_org_filter'), ) def test_positive_list_filter_by_org_sort_by_date( - module_entitlement_manifest_org, rh_repo, custom_repo, filter_by_org, sort_by_date + module_sca_manifest_org, rh_repo, custom_repo, filter_by_org, sort_by_date, module_target_sat ): """Filter by organization and sort by date. @@ -1060,7 +948,8 @@ def test_positive_list_filter_by_org_sort_by_date( :expectedresults: Errata are filtered by org and sorted by date. """ filter_sort_errata( - module_entitlement_manifest_org, + sat=module_target_sat, + org=module_sca_manifest_org, sort_by_date=sort_by_date, filter_by_org=filter_by_org, ) @@ -1189,7 +1078,7 @@ def test_positive_list_filter_by_org(target_sat, products_with_repos, filter_by_ @pytest.mark.run_in_one_thread @pytest.mark.tier3 -def test_positive_list_filter_by_cve(module_entitlement_manifest_org, rh_repo, target_sat): +def test_positive_list_filter_by_cve(module_sca_manifest_org, rh_repo, target_sat): """Filter errata by CVE :id: 7791137c-95a7-4518-a56b-766a5680c5fb @@ -1204,7 +1093,7 @@ def test_positive_list_filter_by_cve(module_entitlement_manifest_org, rh_repo, t target_sat.cli.RepositorySet.enable( { 'name': REPOSET['rhva6'], - 'organization-id': module_entitlement_manifest_org.id, + 'organization-id': module_sca_manifest_org.id, 'product': PRDS['rhel'], 'releasever': '6Server', 'basearch': 'x86_64', @@ -1213,14 +1102,14 @@ def test_positive_list_filter_by_cve(module_entitlement_manifest_org, rh_repo, t target_sat.cli.Repository.synchronize( { 'name': REPOS['rhva6']['name'], - 'organization-id': module_entitlement_manifest_org.id, + 'organization-id': module_sca_manifest_org.id, 'product': PRDS['rhel'], } ) repository_info = target_sat.cli.Repository.info( { 'name': REPOS['rhva6']['name'], - 'organization-id': module_entitlement_manifest_org.id, + 'organization-id': module_sca_manifest_org.id, 'product': PRDS['rhel'], } ) diff --git a/tests/foreman/cli/test_registration.py b/tests/foreman/cli/test_registration.py index 25b8c0a2135..633fbf3be9f 100644 --- a/tests/foreman/cli/test_registration.py +++ b/tests/foreman/cli/test_registration.py @@ -20,6 +20,7 @@ from robottelo.config import settings from robottelo.constants import CLIENT_PORT +from robottelo.exceptions import CLIReturnCodeError pytestmark = pytest.mark.tier1 @@ -171,3 +172,19 @@ def test_negative_register_twice(module_ak_with_cv, module_org, rhel_contenthost # host being already registered. assert result.status == 1 assert 'This system is already registered' in str(result.stderr) + + +@pytest.mark.tier1 +def test_negative_global_registration_without_ak(module_target_sat): + """Attempt to register a host without ActivationKey + + :id: e48a6260-97e0-4234-a69c-77bbbcde85df + + :expectedresults: Generate command is disabled without ActivationKey + """ + with pytest.raises(CLIReturnCodeError) as context: + module_target_sat.cli.HostRegistration.generate_command(options=None) + assert ( + 'Failed to generate registration command:\n Missing activation key!' + in context.value.message + ) diff --git a/tests/foreman/cli/test_repository.py b/tests/foreman/cli/test_repository.py index d1f434ce010..1ca398b9ff4 100644 --- a/tests/foreman/cli/test_repository.py +++ b/tests/foreman/cli/test_repository.py @@ -2553,8 +2553,8 @@ def test_positive_sync_ansible_collection(self, repo, module_target_sat): :parametrized: yes """ - module_target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) - repo = module_target_sat.cli_factory.Repository.info({'id': repo['id']}) + module_target_sat.cli.Repository.synchronize({'id': repo['id']}) + repo = module_target_sat.cli.Repository.info({'id': repo['id']}) assert repo['sync']['status'] == 'Success' @pytest.mark.tier2 @@ -2586,8 +2586,8 @@ def test_positive_export_ansible_collection(self, repo, module_org, target_sat): """ import_org = target_sat.cli_factory.make_org() - target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + target_sat.cli.Repository.synchronize({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) assert repo['sync']['status'] == 'Success' # export result = target_sat.cli.ContentExport.completeLibrary({'organization-id': module_org.id}) @@ -2603,15 +2603,15 @@ def test_positive_export_ansible_collection(self, repo, module_org, target_sat): {'name': 'Import-Library', 'organization-label': import_org['label']} ) assert cv['description'] == 'Content View used for importing into library' - prods = target_sat.cli_factory.Product.list({'organization-id': import_org['id']}) - prod = target_sat.cli_factory.Product.info( + prods = target_sat.cli.Product.list({'organization-id': import_org['id']}) + prod = target_sat.cli.Product.info( {'id': prods[0]['id'], 'organization-id': import_org['id']} ) ac_content = [ cont for cont in prod['content'] if cont['content-type'] == 'ansible_collection' ] assert len(ac_content) > 0 - repo = target_sat.cli_factory.Repository.info( + repo = target_sat.cli.Repository.info( {'name': ac_content[0]['repo-name'], 'product-id': prod['id']} ) result = target_sat.execute(f'curl {repo["published-at"]}') @@ -2646,8 +2646,8 @@ def test_positive_sync_ansible_collection_from_satellite(self, repo, target_sat) """ import_org = target_sat.cli_factory.make_org() - target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + target_sat.cli.Repository.synchronize({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) assert repo['sync']['status'] == 'Success' published_url = repo['published-at'] # sync from different org @@ -2664,8 +2664,8 @@ def test_positive_sync_ansible_collection_from_satellite(self, repo, target_sat) [{ name: theforeman.operations, version: "0.1.0"}]}', } ) - target_sat.cli_factory.Repository.synchronize({'id': repo_2['id']}) - repo_2_status = target_sat.cli_factory.Repository.info({'id': repo_2['id']}) + target_sat.cli.Repository.synchronize({'id': repo_2['id']}) + repo_2_status = target_sat.cli.Repository.info({'id': repo_2['id']}) assert repo_2_status['sync']['status'] == 'Success' @@ -2689,8 +2689,8 @@ def test_positive_sync_publish_promote_cv(self, repo, module_org, target_sat): lifecycle environment """ lce = target_sat.cli_factory.make_lifecycle_environment({'organization-id': module_org.id}) - target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) - synced_repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + target_sat.cli.Repository.synchronize({'id': repo['id']}) + synced_repo = target_sat.cli.Repository.info({'id': repo['id']}) assert synced_repo['sync']['status'].lower() == 'success' assert synced_repo['content-counts']['packages'] == '35' cv = target_sat.cli_factory.make_content_view({'organization-id': module_org.id}) @@ -2724,7 +2724,7 @@ def test_positive_sync(self, repo, module_org, module_product, target_sat): :expectedresults: drpms can be listed in repository """ - target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) + target_sat.cli.Repository.synchronize({'id': repo['id']}) result = target_sat.execute( f"ls /var/lib/pulp/published/yum/https/repos/{module_org.label}/Library" f"/custom/{module_product.label}/{repo['label']}/drpms/ | grep .drpm" @@ -2747,7 +2747,7 @@ def test_positive_sync_publish_cv(self, repo, module_org, module_product, target :expectedresults: drpms can be listed in content view """ - target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) + target_sat.cli.Repository.synchronize({'id': repo['id']}) cv = target_sat.cli_factory.make_content_view({'organization-id': module_org.id}) target_sat.cli.ContentView.add_repository({'id': cv['id'], 'repository-id': repo['id']}) target_sat.cli.ContentView.publish({'id': cv['id']}) @@ -2776,7 +2776,7 @@ def test_positive_sync_publish_promote_cv(self, repo, module_org, module_product lifecycle environment """ lce = target_sat.cli_factory.make_lifecycle_environment({'organization-id': module_org.id}) - target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) + target_sat.cli.Repository.synchronize({'id': repo['id']}) cv = target_sat.cli_factory.make_content_view({'organization-id': module_org.id}) target_sat.cli.ContentView.add_repository({'id': cv['id'], 'repository-id': repo['id']}) target_sat.cli.ContentView.publish({'id': cv['id']}) @@ -3012,7 +3012,7 @@ def test_positive_upload_file_to_file_repo(self, repo_options, repo, target_sat) local_path=DataFile.RPM_TO_UPLOAD, remote_path=f"/tmp/{RPM_TO_UPLOAD}", ) - result = target_sat.cli_factory.Repository.upload_content( + result = target_sat.cli.Repository.upload_content( { 'name': repo['name'], 'organization': repo['organization'], @@ -3021,7 +3021,7 @@ def test_positive_upload_file_to_file_repo(self, repo_options, repo, target_sat) } ) assert f"Successfully uploaded file '{RPM_TO_UPLOAD}'" in result[0]['message'] - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) assert repo['content-counts']['files'] == '1' filesearch = entities.File().search( query={"search": f"name={RPM_TO_UPLOAD} and repository={repo['name']}"} @@ -3077,7 +3077,7 @@ def test_positive_remove_file(self, repo, target_sat): local_path=DataFile.RPM_TO_UPLOAD, remote_path=f"/tmp/{RPM_TO_UPLOAD}", ) - result = target_sat.cli_factory.Repository.upload_content( + result = target_sat.cli.Repository.upload_content( { 'name': repo['name'], 'organization': repo['organization'], @@ -3086,13 +3086,13 @@ def test_positive_remove_file(self, repo, target_sat): } ) assert f"Successfully uploaded file '{RPM_TO_UPLOAD}'" in result[0]['message'] - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) assert int(repo['content-counts']['files']) > 0 files = target_sat.cli.File.list({'repository-id': repo['id']}) - target_sat.cli_factory.Repository.remove_content( + target_sat.cli.Repository.remove_content( {'id': repo['id'], 'ids': [file_['id'] for file_ in files]} ) - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) assert repo['content-counts']['files'] == '0' @pytest.mark.tier2 @@ -3130,8 +3130,8 @@ def test_positive_remote_directory_sync(self, repo, module_target_sat): :expectedresults: entire directory is synced over http """ - module_target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) - repo = module_target_sat.cli_factory.Repository.info({'id': repo['id']}) + module_target_sat.cli.Repository.synchronize({'id': repo['id']}) + repo = module_target_sat.cli.Repository.info({'id': repo['id']}) assert repo['sync']['status'] == 'Success' assert repo['content-counts']['files'] == '2' @@ -3168,8 +3168,8 @@ def test_positive_file_repo_local_directory_sync(self, repo, target_sat): f'wget -P {CUSTOM_LOCAL_FOLDER} -r -np -nH --cut-dirs=5 -R "index.html*" ' f'{CUSTOM_FILE_REPO}' ) - target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + target_sat.cli.Repository.synchronize({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) assert int(repo['content-counts']['files']) > 1 @pytest.mark.tier2 @@ -3208,8 +3208,8 @@ def test_positive_symlinks_sync(self, repo, target_sat): ) target_sat.execute(f'ln -s {CUSTOM_LOCAL_FOLDER} /{gen_string("alpha")}') - target_sat.cli_factory.Repository.synchronize({'id': repo['id']}) - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + target_sat.cli.Repository.synchronize({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) assert int(repo['content-counts']['files']) > 1 @pytest.mark.tier2 @@ -3242,7 +3242,7 @@ def test_file_repo_contains_only_newer_file(self, repo_options, repo, target_sat """ text_file_name = f'test-{gen_string("alpha", 5)}.txt'.lower() target_sat.execute(f'echo "First File" > /tmp/{text_file_name}') - result = target_sat.cli_factory.Repository.upload_content( + result = target_sat.cli.Repository.upload_content( { 'name': repo['name'], 'organization': repo['organization'], @@ -3251,7 +3251,7 @@ def test_file_repo_contains_only_newer_file(self, repo_options, repo, target_sat } ) assert f"Successfully uploaded file '{text_file_name}'" in result[0]['message'] - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) # Assert there is only one file assert repo['content-counts']['files'] == '1' filesearch = entities.File().search( @@ -3260,7 +3260,7 @@ def test_file_repo_contains_only_newer_file(self, repo_options, repo, target_sat assert text_file_name == filesearch[0].name # Create new version of the file by changing the text target_sat.execute(f'echo "Second File" > /tmp/{text_file_name}') - result = target_sat.cli_factory.Repository.upload_content( + result = target_sat.cli.Repository.upload_content( { 'name': repo['name'], 'organization': repo['organization'], @@ -3269,7 +3269,7 @@ def test_file_repo_contains_only_newer_file(self, repo_options, repo, target_sat } ) assert f"Successfully uploaded file '{text_file_name}'" in result[0]['message'] - repo = target_sat.cli_factory.Repository.info({'id': repo['id']}) + repo = target_sat.cli.Repository.info({'id': repo['id']}) # Assert there is still only one file assert repo['content-counts']['files'] == '1' filesearch = entities.File().search( diff --git a/tests/foreman/cli/test_satellitesync.py b/tests/foreman/cli/test_satellitesync.py index 7fed3bd1586..aa660748303 100644 --- a/tests/foreman/cli/test_satellitesync.py +++ b/tests/foreman/cli/test_satellitesync.py @@ -101,23 +101,6 @@ def function_import_org_with_manifest(target_sat, function_import_org): return function_import_org -@pytest.fixture(scope='class') -def docker_repo(module_target_sat, module_org): - product = module_target_sat.cli_factory.make_product({'organization-id': module_org.id}) - repo = module_target_sat.cli_factory.make_repository( - { - 'organization-id': module_org.id, - 'product-id': product['id'], - 'content-type': REPO_TYPE['docker'], - 'download-policy': 'immediate', - 'url': 'https://quay.io', - 'docker-upstream-name': 'quay/busybox', - } - ) - module_target_sat.cli.Repository.synchronize({'id': repo['id']}) - return repo - - @pytest.fixture(scope='module') def module_synced_custom_repo(module_target_sat, module_org, module_product): repo = module_target_sat.cli_factory.make_repository( @@ -499,7 +482,7 @@ def class_export_entities(module_org, module_target_sat): exporting_repo = module_target_sat.cli_factory.make_repository( { 'name': exporting_repo_name, - 'mirror-on-sync': 'no', + 'mirroring-policy': 'mirror_content_only', 'download-policy': 'immediate', 'product-id': product['id'], } @@ -1224,6 +1207,7 @@ def test_postive_export_cv_with_mixed_content_repos( :BZ: 1726457 :customerscenario: true + """ content_view = target_sat.cli_factory.make_content_view( {'organization-id': function_org.id} @@ -1253,57 +1237,6 @@ def test_postive_export_cv_with_mixed_content_repos( exported_packages = target_sat.cli.Package.list( {'content-view-version-id': exporting_cvv['id']} ) - product = target_sat.cli_factory.make_product( - { - 'organization-id': function_org.id, - 'name': gen_string('alpha'), - } - ) - nonyum_repo = target_sat.cli_factory.make_repository( - { - 'content-type': 'docker', - 'docker-upstream-name': 'quay/busybox', - 'organization-id': function_org.id, - 'product-id': product['id'], - 'url': CONTAINER_REGISTRY_HUB, - }, - ) - target_sat.cli.Repository.synchronize({'id': nonyum_repo['id']}) - yum_repo = target_sat.cli_factory.make_repository( - { - 'name': gen_string('alpha'), - 'download-policy': 'immediate', - 'mirror-on-sync': 'no', - 'product-id': product['id'], - } - ) - target_sat.cli.Repository.synchronize({'id': yum_repo['id']}) - content_view = target_sat.cli_factory.make_content_view( - {'organization-id': function_org.id} - ) - # Add docker and yum repo - target_sat.cli.ContentView.add_repository( - { - 'id': content_view['id'], - 'organization-id': function_org.id, - 'repository-id': nonyum_repo['id'], - } - ) - target_sat.cli.ContentView.add_repository( - { - 'id': content_view['id'], - 'organization-id': function_org.id, - 'repository-id': yum_repo['id'], - } - ) - target_sat.cli.ContentView.publish({'id': content_view['id']}) - exporting_cv_id = target_sat.cli.ContentView.info({'id': content_view['id']}) - assert len(exporting_cv_id['versions']) == 1 - exporting_cvv_id = exporting_cv_id['versions'][0] - # check packages - exported_packages = target_sat.cli.Package.list( - {'content-view-version-id': exporting_cvv_id['id']} - ) assert len(exported_packages) # Verify export directory is empty assert target_sat.validate_pulp_filepath(function_org, PULP_EXPORT_DIR) == '' diff --git a/tests/foreman/destructive/test_clone.py b/tests/foreman/destructive/test_clone.py index 60dfc31ca29..f29fd0d22cb 100644 --- a/tests/foreman/destructive/test_clone.py +++ b/tests/foreman/destructive/test_clone.py @@ -29,7 +29,9 @@ @pytest.mark.e2e @pytest.mark.parametrize('backup_type', ['online', 'offline']) @pytest.mark.parametrize('skip_pulp', [False, True], ids=['include_pulp', 'skip_pulp']) -def test_positive_clone_backup(target_sat, sat_ready_rhel, backup_type, skip_pulp): +def test_positive_clone_backup( + target_sat, sat_ready_rhel, backup_type, skip_pulp, custom_synced_repo +): """Make an online/offline backup with/without pulp data of Satellite and clone it (restore it). :id: 5b9182d5-6789-4d2c-bcc3-6641b96ab277 @@ -45,13 +47,15 @@ def test_positive_clone_backup(target_sat, sat_ready_rhel, backup_type, skip_pul :parametrized: yes - :BZ: 2142514 + :BZ: 2142514, 2013776 :customerscenario: true """ rhel_version = sat_ready_rhel._v_major sat_version = 'stream' if target_sat.is_stream else target_sat.version + pulp_artifact_len = len(target_sat.execute('ls /var/lib/pulp/media/artifact').stdout) + # SATELLITE PART - SOURCE SERVER # Enabling and starting services assert target_sat.cli.Service.enable().status == 0 @@ -66,16 +70,6 @@ def test_positive_clone_backup(target_sat, sat_ready_rhel, backup_type, skip_pul assert backup_result.status == 0 sat_backup_dir = backup_result.stdout.strip().split()[-2] - if skip_pulp: - # Copying satellite pulp data to target RHEL - assert sat_ready_rhel.execute('mkdir -p /var/lib/pulp').status == 0 - assert ( - target_sat.execute( - f'''sshpass -p "{SSH_PASS}" scp -o StrictHostKeyChecking=no \ - -r /var/lib/pulp root@{sat_ready_rhel.hostname}:/var/lib/pulp/pulp''' - ).status - == 0 - ) # Copying satellite backup to target RHEL assert ( target_sat.execute( @@ -118,6 +112,22 @@ def test_positive_clone_backup(target_sat, sat_ready_rhel, backup_type, skip_pul cloned_sat = Satellite(sat_ready_rhel.hostname) assert cloned_sat.cli.Health.check().status == 0 + # If --skip-pulp-data make sure you can rsync /var/lib/pulp over per BZ#2013776 + if skip_pulp: + # Copying satellite pulp data to target RHEL + assert ( + target_sat.execute( + f'sshpass -p "{SSH_PASS}" rsync -e "ssh -o StrictHostKeyChecking=no" --archive --partial --progress --compress ' + f'/var/lib/pulp root@{sat_ready_rhel.hostname}:/var/lib/' + ).status + == 0 + ) + + # Make sure all of the pulp data that was on the original Satellite is on the clone + assert ( + len(sat_ready_rhel.execute('ls /var/lib/pulp/media/artifact').stdout) == pulp_artifact_len + ) + @pytest.mark.pit_server def test_positive_list_tasks(target_sat): diff --git a/tests/foreman/installer/test_installer.py b/tests/foreman/installer/test_installer.py index 2ff6321d682..c8268fd3882 100644 --- a/tests/foreman/installer/test_installer.py +++ b/tests/foreman/installer/test_installer.py @@ -1385,7 +1385,7 @@ def sat_non_default_install(module_sat_ready_rhels): installer_args = [ 'scenario satellite', f'foreman-initial-admin-password {settings.server.admin_password}', - 'foreman-rails-cache-store type:redis', + 'foreman-rails-cache-store type:file', 'foreman-proxy-content-pulpcore-hide-guarded-distributions false', ] install_satellite(module_sat_ready_rhels[1], installer_args) @@ -1467,8 +1467,8 @@ def test_foreman_rails_cache_store(sat_non_default_install): :id: 379a2fe8-1085-4a7f-8ac3-24c421412f12 :steps: - 1. Install Satellite. - 2. Verify that foreman-redis package is installed. + 1. Install Satellite with option foreman-rails-cache-store type:file + 2. Verify that foreman-redis package is not installed. 3. Check /etc/foreman/settings.yaml :CaseImportance: Medium @@ -1478,9 +1478,9 @@ def test_foreman_rails_cache_store(sat_non_default_install): :BZ: 2063717, 2165092 """ # Verify foreman-rails-cache-store option works - assert sat_non_default_install.execute('rpm -q foreman-redis').status == 0 + assert sat_non_default_install.execute('rpm -q foreman-redis').status == 1 settings_file = sat_non_default_install.load_remote_yaml_file(FOREMAN_SETTINGS_YML) - assert settings_file.rails_cache_store.type == 'redis' + assert settings_file.rails_cache_store.type == 'file' @pytest.mark.e2e @@ -1796,8 +1796,14 @@ def test_satellite_installation(installer_satellite): 2. satellite-installer runs successfully 3. no unexpected errors in logs 4. satellite-maintain health check runs successfully + 5. redis is set as default foreman cache :CaseImportance: Critical """ common_sat_install_assertions(installer_satellite) + + # Verify foreman-redis is installed and set as default cache for rails + assert installer_satellite.execute('rpm -q foreman-redis').status == 0 + settings_file = installer_satellite.load_remote_yaml_file(FOREMAN_SETTINGS_YML) + assert settings_file.rails_cache_store.type == 'redis' diff --git a/tests/foreman/maintain/test_health.py b/tests/foreman/maintain/test_health.py index 3793dad8b01..313c2d89fe9 100644 --- a/tests/foreman/maintain/test_health.py +++ b/tests/foreman/maintain/test_health.py @@ -320,8 +320,8 @@ def _finalize(): @pytest.mark.include_capsule -def test_positive_health_check_validate_yum_config(sat_maintain): - """Verify validate-yum-config +def test_positive_health_check_validate_dnf_config(sat_maintain): + """Verify validate-dnf-config :id: b50c8866-6175-4286-8106-561945726023 @@ -329,26 +329,26 @@ def test_positive_health_check_validate_yum_config(sat_maintain): :steps: 1. configure yum exclude. - 2. Run satellite-maintain health check --label validate-yum-config + 2. Run satellite-maintain health check --label validate-dnf-config 3. Assert that excluded packages are listed in output. 4. remove yum exclude configured in step 1. - :expectedresults: validate-yum-config should work. + :expectedresults: validate-dnf-config should work. :BZ: 1669498 :customerscenario: true """ - file = '/etc/yum.conf' - yum_exclude = 'exclude=cat*' - failure_message = 'Unset this configuration as it is risky while yum update or upgrade!' - sat_maintain.execute(f'sed -i "$ a {yum_exclude}" {file}') - result = sat_maintain.cli.Health.check(options={'label': 'validate-yum-config'}) + file = '/etc/dnf/dnf.conf' + dnf_exclude = 'exclude=cat*' + failure_message = 'Unset this configuration as it is risky while dnf update or upgrade!' + sat_maintain.execute(f'sed -i "$ a {dnf_exclude}" {file}') + result = sat_maintain.cli.Health.check(options={'label': 'validate-dnf-config'}) assert result.status == 1 - assert yum_exclude in result.stdout + assert dnf_exclude in result.stdout assert failure_message in result.stdout - sat_maintain.execute(f'sed -i "/{yum_exclude}/d" {file}') - result = sat_maintain.cli.Health.check(options={'label': 'validate-yum-config'}) + sat_maintain.execute(f'sed -i "/{dnf_exclude}/d" {file}') + result = sat_maintain.cli.Health.check(options={'label': 'validate-dnf-config'}) assert result.status == 0 assert 'FAIL' not in result.stdout diff --git a/tests/foreman/ui/test_audit.py b/tests/foreman/ui/test_audit.py index ca506d21292..822f7bcb1bf 100644 --- a/tests/foreman/ui/test_audit.py +++ b/tests/foreman/ui/test_audit.py @@ -1,6 +1,6 @@ """Test class for Audit UI -:Requirement: Audit +:Requirement: AuditLog :CaseAutomation: Automated diff --git a/tests/foreman/ui/test_capsulecontent.py b/tests/foreman/ui/test_capsulecontent.py new file mode 100644 index 00000000000..6d1f30bd95c --- /dev/null +++ b/tests/foreman/ui/test_capsulecontent.py @@ -0,0 +1,237 @@ +"""Capsule-Content related tests being run through UI. + +:Requirement: Capsule-Content + +:CaseAutomation: Automated + +:CaseLevel: System + +:CaseComponent: Capsule-Content + +:team: Phoenix-content + +:TestType: Functional + +:CaseImportance: High + +:Upstream: No +""" +import pytest + +from robottelo.config import settings +from robottelo.constants import DEFAULT_CV +from robottelo.constants.repos import ANSIBLE_GALAXY, CUSTOM_FILE_REPO + + +@pytest.fixture(scope='module', autouse=True) +def capsule_default_org(module_target_sat, module_capsule_configured, default_org): + """Add new Capsule to the Default Organization""" + module_target_sat.cli.Capsule.update( + { + 'name': module_capsule_configured.hostname, + 'organization-ids': default_org.id, + } + ) + + +@pytest.mark.parametrize( + 'repos_collection', + [ + { + 'distro': 'rhel8', + 'YumRepository': {'url': settings.repos.module_stream_1.url}, + 'FileRepository': {'url': CUSTOM_FILE_REPO}, + 'DockerRepository': { + 'url': 'https://quay.io', + 'upstream_name': 'libpod/testimage', + }, + 'AnsibleRepository': { + 'url': ANSIBLE_GALAXY, + 'requirements': [ + {'name': 'theforeman.foreman', 'version': '2.1.0'}, + {'name': 'theforeman.operations', 'version': '0.1.0'}, + ], + }, + } + ], + indirect=True, +) +def test_positive_content_counts_for_mixed_cv( + target_sat, + module_capsule_configured, + repos_collection, + function_org, + function_lce, + function_lce_library, +): + """Verify the content counts for a mixed-content CV + + :id: b150f813-ae98-452b-9ad2-7f4ea88277c9 + + :parametrized: yes + + :setup: + 1. A content view with repos of all content types + published into CVV and promoted to an LCE. + + :steps: + 1. Assign the Capsule with the LCE where the setup CVV is promoted to. + 2. Check the capsule lists correct LCE and CV names but no content counts before sync. + 3. Sync the Capsule and get the content counts again. + 4. Get the content counts from Satellite side and compare them with Capsule. + 5. Refresh the counts and check the Counts update task was triggered. + 6. Remove the LCEs from Capsule and ensure they are not listed anymore. + + :expectedresults: + 1. Capsule returns 'N/A' for content counts until it is synced. + 2. After sync the content counts from Capsule match those from Satellite. + 3. Update counts task can be triggered from the UI. + 4. After LCE removal content counts are not listed anymore. + """ + repos_collection.setup_content(function_org.id, function_lce.id, upload_manifest=False) + cv_id = repos_collection.setup_content_data['content_view']['id'] + cv = target_sat.api.ContentView(id=cv_id).read() + cvv = cv.version[-1].read() + lces = [function_lce.name, function_lce_library.name] + + with target_sat.ui_session() as session: + session.capsule.edit( + module_capsule_configured.hostname, add_organizations=[function_org.name] + ) + session.organization.select(org_name=function_org.name) + + # Assign the Capsule with the LCE where the setup CVV is promoted to. + session.capsule.edit( + module_capsule_configured.hostname, + add_lces=lces, + ) + + # Check the capsule lists correct LCE and CV names but no content counts before sync. + details = session.capsule.read_details(module_capsule_configured.hostname) + assert set(lces) == set(details['content']), 'Wrong LCEs listed' + assert function_lce.name in details['content'], 'Assigned LCE not listed' + + for lce in lces: + assert cv.name in details['content'][lce], 'Assigned CV not listed' + assert ( + 'N/A' in details['content'][lce]['top_row_content']['Last sync'] + ), 'LCE should be marked as unsynced' + + assert ( + details['content'][lce][cv.name]['mid_row_content']['Version'] + == f'Version {cvv.version}' + ), 'CV version does not match' + assert not details['content'][lce][cv.name]['mid_row_content'][ + 'Synced' + ], 'CV should not be marked as synced' + + repos_details = details['content'][lce][cv.name]['expanded_repo_details'][1:] + assert all( + [repo[1] == repo[2] == 'N/A' for repo in repos_details] + ), 'Expected all content counts as N/A' + + if lce == 'Library': + # Library should contain the Default Org View too + assert DEFAULT_CV in details['content'][lce], 'Default Org View not listed' + + assert ( + details['content'][lce][DEFAULT_CV]['mid_row_content']['Version'] + == 'Version 1.0' + ), 'CV version does not match' + assert not details['content'][lce][DEFAULT_CV]['mid_row_content'][ + 'Synced' + ], 'CV should not be marked as synced' + + repos_details = details['content'][lce][DEFAULT_CV]['expanded_repo_details'][1:] + assert all( + [repo[1] == repo[2] == 'N/A' for repo in repos_details] + ), 'Expected all content counts as N/A' + + # Sync the Capsule and get the content counts again. + session.capsule.optimized_sync(module_capsule_configured.hostname) + target_sat.wait_for_tasks( + search_query='label = Actions::Katello::CapsuleContent::Sync', + search_rate=10, + max_tries=10, + ) + target_sat.wait_for_tasks( + search_query='label = Actions::Katello::CapsuleContent::UpdateContentCounts', + search_rate=5, + max_tries=5, + ) + details = session.capsule.read_details(module_capsule_configured.hostname) + + # Get the content counts from Satellite side and compare them with Capsule. + sat_repos = [target_sat.api.Repository(id=repo.id).read() for repo in cvv.repository] + for lce in lces: + assert ( + 'ago' in details['content'][lce]['top_row_content']['Last sync'] + ), 'LCE should be marked as synced' + assert details['content'][lce][cv.name]['mid_row_content'][ + 'Synced' + ], 'CV should be marked as synced' + repos_details = details['content'][lce][cv.name]['expanded_repo_details'][1:] + + for s_repo in sat_repos: + c_repo = next(r for r in repos_details if r[0] == s_repo.name) + assert c_repo, 'Repository not listed' + if s_repo.content_type == 'yum': + assert ( + f'{s_repo.content_counts["rpm"]} Packages' in c_repo + ), 'RPMs count does not match' + assert ( + f'{s_repo.content_counts["erratum"]} Errata' in c_repo + ), 'Errata count does not match' + assert ( + f'{s_repo.content_counts["package_group"]} Package groups' in c_repo + ), 'Package groups count does not match' + # assert ( + # f'{s_repo.content_counts["module_stream"]} Module streams' in c_repo + # ), 'Module streams count does not match' + elif s_repo.content_type == 'file': + assert ( + f'{s_repo.content_counts["file"]} Files' in c_repo + ), 'Files count does not match' + elif s_repo.content_type == 'docker': + assert ( + f'{s_repo.content_counts["docker_tag"]} Container tags' in c_repo + ), 'Container tags count does not match' + assert ( + f'{s_repo.content_counts["docker_manifest"]} Container manifests' in c_repo + ), 'Container manifests count does not match' + # assert ( + # f'{s_repo.content_counts["docker_manifest_list"]} Container manifest lists' + # in c_repo + # ), 'Container manifest lists count does not match' + elif s_repo.content_type == 'ansible_collection': + assert ( + f'{s_repo.content_counts["ansible_collection"]} Ansible collections' + in c_repo + ), 'Ansible collections count does not match' + + # Refresh the counts and check the Counts update task was triggered. + for lce in lces: + t1 = target_sat.api.ForemanTask().search( + query={ + 'search': 'label = Actions::Katello::CapsuleContent::UpdateContentCounts', + 'per_page': '1000', + } + ) + session.capsule.refresh_lce_counts(module_capsule_configured.hostname, lce_name=lce) + target_sat.wait_for_tasks( + search_query='label = Actions::Katello::CapsuleContent::UpdateContentCounts', + search_rate=5, + max_tries=5, + ) + t2 = target_sat.api.ForemanTask().search( + query={ + 'search': 'label = Actions::Katello::CapsuleContent::UpdateContentCounts', + 'per_page': '1000', + } + ) + assert len(t2) == len(t1) + 1, 'Update CC task was not triggered' + + # Remove the LCEs from Capsule and ensure they are not listed anymore. + session.capsule.edit(module_capsule_configured.hostname, remove_all_lces=True) + details = session.capsule.read_details(module_capsule_configured.hostname) + assert 'content' not in details.keys(), 'Content still listed for removed LCEs' diff --git a/tests/foreman/ui/test_registration.py b/tests/foreman/ui/test_registration.py new file mode 100644 index 00000000000..b70bcb41872 --- /dev/null +++ b/tests/foreman/ui/test_registration.py @@ -0,0 +1,123 @@ +"""Tests for registration. + +:Requirement: Registration + +:CaseLevel: Acceptance + +:CaseComponent: Registration + +:CaseAutomation: Automated + +:CaseImportance: Critical + +:Team: Rocket + +:TestType: Functional + +:Upstream: No +""" +from airgun.exceptions import DisabledWidgetError +import pytest + +from robottelo.utils.datafactory import gen_string + +pytestmark = pytest.mark.tier1 + + +def test_positive_verify_default_values_for_global_registration( + module_target_sat, + default_org, +): + """Check for all the Default values pre-populated in the global registration template + + :id: 34122bf3-ae23-47ca-ba3d-da0653d8fd33 + + :expectedresults: Default fields in the form should be auto-populated + e.g. organization, location, rex, insights setup, etc + + :CaseLevel: Component + + :steps: + 1. Check for the default values in the global registration template + """ + module_target_sat.cli_factory.make_activation_key( + {'organization-id': default_org.id, 'name': gen_string('alpha')} + ) + with module_target_sat.ui_session() as session: + cmd = session.host.get_register_command( + full_read=True, + ) + assert cmd['general']['organization'] == 'Default Organization' + assert cmd['general']['location'] == 'Default Location' + assert cmd['general']['capsule'] == 'Nothing to select.' + assert cmd['general']['operating_system'] == '' + assert cmd['general']['host_group'] == 'Nothing to select.' + assert cmd['general']['insecure'] is False + assert cmd['advanced']['setup_rex'] == 'Inherit from host parameter (yes)' + assert cmd['advanced']['setup_insights'] == 'Inherit from host parameter (yes)' + assert cmd['advanced']['token_life_time'] == '4' + assert cmd['advanced']['rex_pull_mode'] == 'Inherit from host parameter (no)' + assert cmd['advanced']['update_packages'] is False + assert cmd['advanced']['ignore_error'] is False + assert cmd['advanced']['force'] is False + + +@pytest.mark.tier2 +def test_positive_org_loc_change_for_registration( + module_activation_key, + module_org, + module_location, + target_sat, +): + """Changing the organization and location to check if correct org and loc is updated on the global registration page as well as in the command + + :id: e83ed6bc-ceae-4021-87fe-3ecde1cbf347 + + :expectedresults: organization and location is updated correctly on the global registration page as well as in the command. + + :CaseLevel: Component + + :CaseImportance: Medium + """ + new_org = target_sat.api.Organization().create() + new_loc = target_sat.api.Location().create() + target_sat.api.ActivationKey(organization=new_org).create() + with target_sat.ui_session() as session: + session.organization.select(org_name=module_org.name) + session.location.select(loc_name=module_location.name) + cmd = session.host.get_register_command() + expected_pairs = [ + f'organization_id={module_org.id}', + f'location_id={module_location.id}', + ] + for pair in expected_pairs: + assert pair in cmd + # changing the org and loc to check if correct org and loc is updated on the registration command + session.organization.select(org_name=new_org.name) + session.location.select(loc_name=new_loc.name) + cmd = session.host.get_register_command() + expected_pairs = [ + f'organization_id={new_org.id}', + f'location_id={new_loc.id}', + ] + for pair in expected_pairs: + assert pair in cmd + + +def test_negative_global_registration_without_ak( + module_target_sat, + module_org, + module_location, +): + """Attempt to register a host without ActivationKey + + :id: 34122bf3-ae23-47ca-ba3d-da0653d8fd36 + + :expectedresults: Generate command is disabled without ActivationKey + """ + with module_target_sat.ui_session() as session: + session.organization.select(org_name=module_org.name) + session.location.select(loc_name=module_location.name) + with pytest.raises(DisabledWidgetError) as context: + session.host.get_register_command() + assert 'Generate registration command button is disabled' in str(context.value)