diff --git a/conftest.py b/conftest.py index ca4cc18cf02..58a886c1596 100644 --- a/conftest.py +++ b/conftest.py @@ -2,6 +2,8 @@ import pytest +from robottelo.config import settings + pytest_plugins = [ # Plugins 'pytest_plugins.auto_vault', @@ -93,3 +95,14 @@ def pytest_runtest_makereport(item, call): # be "setup", "call", "teardown" setattr(item, "report_" + report.when, report) + + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_protocol(item, nextitem): + """Set version source to upstream for tests marked with foremanctl.""" + if item.get_closest_marker('foremanctl'): + settings.set('server.version.source', 'upstream') + yield + settings.set('server.version.source', 'internal') + else: + yield diff --git a/pytest_plugins/markers.py b/pytest_plugins/markers.py index 1562d89c80e..14ca86e3633 100644 --- a/pytest_plugins/markers.py +++ b/pytest_plugins/markers.py @@ -24,6 +24,7 @@ def pytest_configure(config): "ldap: Tests related to ldap authentication", "no_compose : Skip the marked sanity test for nightly compose", "network: Restrict test to specific network environments", + "foremanctl: Tests that require foremanctl", ] markers.extend(module_markers()) for marker in markers: diff --git a/robottelo/config/validators.py b/robottelo/config/validators.py index f2b69db7ea3..7c8a9d54d75 100644 --- a/robottelo/config/validators.py +++ b/robottelo/config/validators.py @@ -14,7 +14,11 @@ Validator('server.hostname', is_type_of=str), Validator('server.hostnames', must_exist=True, is_type_of=list), Validator('server.version.release', must_exist=True), - Validator('server.version.source', default='internal', is_in=['internal', 'ga', 'nightly']), + Validator( + 'server.version.source', + default='internal', + is_in=['internal', 'ga', 'nightly', 'upstream'], + ), Validator('server.version.rhel_version', must_exist=True, cast=str), Validator( 'server.xdist_behavior', must_exist=True, is_in=['run-on-one', 'balance', 'on-demand'] diff --git a/robottelo/hosts.py b/robottelo/hosts.py index 9810ee14640..d2646730921 100644 --- a/robottelo/hosts.py +++ b/robottelo/hosts.py @@ -1577,6 +1577,12 @@ def setup_satellite_repos(self): satellite_repo=settings.repos.satellite_repo, satmaintenance_repo=settings.repos.satmaintenance_repo, ) + elif settings.server.version.source == 'upstream': + self.create_custom_repos( + foreman='https://yum.theforeman.org/nightly/el9/x86_64/', + foreman_plugins='https://yum.theforeman.org/plugins/nightly/el9/x86_64/', + katello='https://yum.theforeman.org/katello/nightly/katello/el9/x86_64/', + ) else: # get ohsnap repofile self.download_repofile( @@ -1955,6 +1961,55 @@ def install_satellite_or_capsule_package(self): self.enable_satellite_or_capsule_module_for_rhel8() assert self.execute(f'dnf -y install {self.product_rpm_name}').status == 0 + def install_satellite_foremanctl(self, enable_fapolicyd=False, enable_fips=False): + # Enable RHEL and Satellite repos + self.register_to_cdn() + self.setup_rhel_repos() + self.setup_satellite_repos() + assert self.execute('dnf copr enable -y @theforeman/foremanctl rhel-9-x86_64').status == 0 + assert self.execute('dnf install -y foremanctl').status == 0 + + if enable_fapolicyd: + assert self.execute('dnf -y install fapolicyd').status == 0 + assert self.execute('systemctl enable --now fapolicyd').status == 0 + assert self.execute('systemctl is-active fapolicyd').status == 0 + if enable_fips: + Broker().execute( + workflow='enable-fips', + target_vm=self.name, + ) + self.connect() + assert self.is_fips_enabled() + + # Configure Satellite firewall to open communication + assert ( + self.execute( + '(which firewall-cmd || dnf -y install firewalld) && systemctl enable --now firewalld' + ).status + == 0 + ), 'firewalld is not present and can\'t be installed' + assert ( + self.execute( + 'firewall-cmd --permanent --add-service RH-Satellite-6 && firewall-cmd --reload' + ).status + == 0 + ) + # Install Satellite and return result + assert ( + self.execute( + f'foremanctl deploy --foreman-initial-admin-username {settings.server.admin_username} --foreman-initial-admin-password {settings.server.admin_password}', + timeout='30m', + ).status + == 0 + ) + assert ( + self.execute( + 'foremanctl deploy --add-feature foreman-proxy --add-feature hammer' + ).status + == 0 + ) + return + def query_db(self, query, db='foreman', output_format='json'): """Execute a PostgreSQL query and return the result. diff --git a/tests/foreman/installer/test_new_installer.py b/tests/foreman/installer/test_new_installer.py new file mode 100644 index 00000000000..c68dd442eab --- /dev/null +++ b/tests/foreman/installer/test_new_installer.py @@ -0,0 +1,121 @@ +"""Smoke tests to check installation health + +:Requirement: Installation + +:CaseAutomation: Automated + +:CaseComponent: Installation + +:Team: Rocket + +:CaseImportance: Critical + +""" + +from broker import Broker +import pytest + +from robottelo.config import settings +from robottelo.hosts import Satellite, get_sat_rhel_version + +pytestmark = [pytest.mark.foremanctl, pytest.mark.build_sanity, pytest.mark.upgrade] + +SATELLITE_SERVICES = [ + 'candlepin', + 'dynflow-sidekiq@orchestrator', + 'dynflow-sidekiq@worker', + 'dynflow-sidekiq@worker-hosts-queue', + 'foreman-proxy', + 'foreman', + 'httpd', + 'postgresql', + 'pulp-api', + 'pulp-content', + 'pulp-worker@*', + 'redis', +] + + +def common_sat_install_assertions(satellite): + # no errors/failures in journald + result = satellite.execute( + r'journalctl --quiet --no-pager --boot --priority err -u "dynflow-sidekiq*" -u "foreman-proxy" -u "foreman" -u "httpd" -u "postgresql" -u "pulp-api" -u "pulp-content" -u "pulp-worker*" -u "redis" -u "candlepin"' + ) + assert not result.stdout + # no errors/failures in /var/log/httpd/* + result = satellite.execute(r'grep -iR "error" /var/log/httpd/*') + assert not result.stdout + # # no errors/failures in /var/log/candlepin/* + result = satellite.execute(r'grep -iR "error" /var/log/candlepin/*') + assert not result.stdout + httpd_log = satellite.execute('journalctl --unit=httpd') + assert 'WARNING' not in httpd_log.stdout + + +@pytest.fixture(scope='module') +def module_sat_ready_rhel(request): + with Broker( + workflow=settings.server.deploy_workflows.os, + deploy_rhel_version=get_sat_rhel_version().major, + deploy_flavor=settings.flavors.default, + deploy_network_type=settings.server.network_type, + host_class=Satellite, + ) as sat: + sat.install_satellite_foremanctl( + enable_fapolicyd=(request.param == 'fapolicyd'), enable_fips=(request.param == 'fips') + ) + yield sat + + +@pytest.mark.first_sanity +@pytest.mark.parametrize('module_sat_ready_rhel', ['default', 'fips', 'fapolicyd'], indirect=True) +def test_satellite_installation_with_foremanctl(module_sat_ready_rhel): + """Run a basic Satellite installation + + :id: 661206f3-2eec-403c-af26-3c5cadcd5769 + + :steps: + 1. Get RHEL Host + 2. Configure satellite repos + 3. Install satellite using foremanctl + 4. Run foremanctl deploy + + :expectedresults: + 1. foremanctl deploy runs successfully + 2. no unexpected errors in logs + """ + common_sat_install_assertions(module_sat_ready_rhel) + + +@pytest.mark.parametrize('service', SATELLITE_SERVICES) +def test_positive_check_installer_service_running(service, module_sat_ready_rhel): + """Check if all Satellite services is running + + :id: 5389c174-7ab1-4e9d-b2aa-66d80fd6dc5h + + :steps: + 1. Verify a service is active with systemctl is-active + + :expectedresults: All Satellite services are active + """ + is_active = module_sat_ready_rhel.execute(f'systemctl is-active {service}') + status = module_sat_ready_rhel.execute(f'systemctl status {service}') + assert is_active.status == 0, status.stdout + + +def test_positive_check_installer_hammer_ping(module_sat_ready_rhel): + """Check if hammer ping reports all services as ok + + :id: 85fd4388-6d94-42f5-bed2-24be38e9f111 + + :steps: + 1. Run the 'hammer ping' command on satellite. + + :expectedresults: All services are active (running) + """ + response = module_sat_ready_rhel.api.Ping().search_json() + assert response['status'] == 'ok' # overall status + services = response['services'] + assert all([service['status'] == 'ok' for service in services.values()]), ( + 'Not all services seem to be up and running!' + )