diff --git a/docs/developer/testing.md b/docs/developer/testing.md index fa6011d85..96c5b80f7 100644 --- a/docs/developer/testing.md +++ b/docs/developer/testing.md @@ -146,6 +146,32 @@ def test_service_port(server): assert server.addr("localhost").port(6379).is_reachable ``` +### Feature guarding + +Some functionality can only be tested when a feature is enabled. + +You can mark an invidivual test to be skipped if needed: + +```python +@pytest.mark.feature("iop") +def test_ingress_service(server): + service = server.service("iop-core-ingress") + assert service.is_running and service.is_enabled +``` + +Often it's better to have an entire file dedicated to a feature and mark the entire file as guarded. + +```python +pytestmark = pytest.mark.feature("iop") + +def test_ingress_service(server): + service = server.service("iop-core-ingress") + assert service.is_running and service.is_enabled + +def test_ingress_http_endpoint(server): + # ... +``` + ### API test The `foremanapi` fixture is an [apypie](https://github.com/Apipie/apypie) `ForemanApi` client that connects to the deployed Foreman instance(authenticated as `admin`/`changeme`). It maps directly to the Foreman REST API — each method takes a resource name that corresponds to an API endpoint: diff --git a/src/playbooks/deploy/deploy.yaml b/src/playbooks/deploy/deploy.yaml index 837d36c98..58c99a033 100644 --- a/src/playbooks/deploy/deploy.yaml +++ b/src/playbooks/deploy/deploy.yaml @@ -13,19 +13,44 @@ - "../../vars/foreman.yml" - "../../vars/base.yaml" pre_tasks: - - name: Add iop databases + - name: Determine databases when: - - "'iop' in enabled_features" - database_mode == 'internal' block: - - name: Include iop databases - ansible.builtin.include_vars: - file: "../../vars/database_iop.yml" + - name: Configure Candlepin database + ansible.builtin.set_fact: + postgresql_databases: "{{ postgresql_databases + postgresql_databases_candlepin }}" + postgresql_users: "{{ postgresql_users + postgresql_users_candlepin }}" + when: + - "'foreman' in enabled_features" + - "'katello' in enabled_features" + + - name: Configure Foreman database + ansible.builtin.set_fact: + postgresql_databases: "{{ postgresql_databases + postgresql_databases_foreman }}" + postgresql_users: "{{ postgresql_users + postgresql_users_foreman }}" + when: + - "'foreman' in enabled_features" - - name: Combine lists + - name: Configure Pulp database ansible.builtin.set_fact: - postgresql_databases: "{{ postgresql_databases + iop_postgresql_databases }}" - postgresql_users: "{{ postgresql_users + iop_postgresql_users }}" + postgresql_databases: "{{ postgresql_databases + postgresql_databases_pulp }}" + postgresql_users: "{{ postgresql_users + postgresql_users_pulp }}" + when: + - "'katello' in enabled_features" + + - name: Add iop databases + when: + - "'iop' in enabled_features" + block: + - name: Include iop databases + ansible.builtin.include_vars: + file: "../../vars/database_iop.yml" + + - name: Combine lists + ansible.builtin.set_fact: + postgresql_databases: "{{ postgresql_databases + iop_postgresql_databases }}" + postgresql_users: "{{ postgresql_users + iop_postgresql_users }}" roles: - role: pre_install - role: checks @@ -40,9 +65,14 @@ when: - database_mode == 'internal' - redis - - candlepin + - role: candlepin + when: + - "'foreman' in enabled_features" + - "'katello' in enabled_features" - httpd - - pulp + - role: pulp + when: + - "'katello' in enabled_features" - foreman - role: systemd_target - role: iop_core diff --git a/src/roles/foreman/tasks/main.yaml b/src/roles/foreman/tasks/main.yaml index f08ac17f9..0105171b5 100644 --- a/src/roles/foreman/tasks/main.yaml +++ b/src/roles/foreman/tasks/main.yaml @@ -313,3 +313,5 @@ oauth1_consumer_key: "{{ foreman_oauth_consumer_key }}" oauth1_consumer_secret: "{{ foreman_oauth_consumer_secret }}" ca_path: "{{ foreman_ca_certificate }}" + when: + - "'katello' in enabled_features" diff --git a/src/vars/database.yml b/src/vars/database.yml index 2a89bed01..3d0d2d8fb 100644 --- a/src/vars/database.yml +++ b/src/vars/database.yml @@ -29,17 +29,29 @@ foreman_database_port: "{{ database_port }}" foreman_database_ssl_mode: "{{ database_ssl_mode }}" foreman_database_ssl_ca: "{{ database_ssl_ca }}" -postgresql_databases: +postgresql_databases_candlepin: - name: "{{ candlepin_database_name }}" owner: "{{ candlepin_database_user }}" + +postgresql_databases_foreman: - name: "{{ foreman_database_name }}" owner: "{{ foreman_database_user }}" + +postgresql_databases_pulp: - name: "{{ pulp_database_name }}" owner: "{{ pulp_database_user }}" -postgresql_users: + +postgresql_users_candlepin: - name: "{{ candlepin_database_user }}" password: "{{ candlepin_database_password }}" + +postgresql_users_foreman: - name: "{{ foreman_database_user }}" password: "{{ foreman_database_password }}" + +postgresql_users_pulp: - name: "{{ pulp_database_user }}" password: "{{ pulp_database_password }}" + +postgresql_databases: [] +postgresql_users: [] diff --git a/src/vars/flavors/foreman.yml b/src/vars/flavors/foreman.yml new file mode 100644 index 000000000..ac29b9597 --- /dev/null +++ b/src/vars/flavors/foreman.yml @@ -0,0 +1,3 @@ +--- +flavor_features: + - foreman diff --git a/tests/conftest.py b/tests/conftest.py index 4883e923a..bcd360a2d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,7 @@ import os import uuid +from functools import cached_property +from pathlib import Path import apypie import paramiko @@ -16,6 +18,39 @@ SSH_CONFIG = './.tmp/ssh-config' +class UserParameters: + def __init__(self, config): + self._config = config + + @property + def _obsah_state(self) -> Path: + # mirror what foremanctl / obsah does + if state := os.environ.get('OBSAH_STATE'): + return Path(state) + + if base := os.environ.get('OBSAH_BASE'): + root = Path(base) + else: + root = self._config.rootpath + return root / '.var' / 'lib' / 'foremanctl' + + def _read_parameters(self): + params_file = self._obsah_state / 'parameters.yaml' + if params_file.exists(): + with params_file.open('r') as f: + return yaml.safe_load(f) + + return None + + @cached_property + def features(self): + # TODO: read the flavor and extract the features from there too + params = self._read_parameters() + if params: + return set(params.get('features', [])) + return set() + + def pytest_addoption(parser): parser.addoption("--certificate-source", action="store", default="default", choices=('default', 'installer', 'custom_server'), help="Certificate source used during deployment") parser.addoption("--database-mode", action="store", default="internal", choices=('internal', 'external'), help="Whether the database is internal or external") @@ -114,6 +149,10 @@ def foremanapi(ssh_config, server_fqdn): api._session.headers['Host'] = server_fqdn return api +@pytest.fixture +def features(pytestconfig): + return pytestconfig.user_parameters.features + @pytest.fixture def organization(foremanapi): @@ -206,35 +245,32 @@ def wait_for_metadata_generate(foremanapi): wait_for_tasks(foremanapi, 'label = Actions::Katello::Repository::MetadataGenerate') -def enabled_features(): - test_dir = os.path.dirname(os.path.abspath(__file__)) - foremanctl_dir = os.path.dirname(test_dir) - params_file = os.path.join(foremanctl_dir, '.var', 'lib', 'foremanctl', 'parameters.yaml') - if os.path.exists(params_file): - with open(params_file, 'r') as f: - features = yaml.safe_load(f).get('features', []) - if isinstance(features, str): - features = features.split() - return features - return [] - - -def is_iop_enabled(): - return 'iop' in enabled_features() - - def pytest_configure(config): - config.addinivalue_line("markers", "iop: tests requiring IOP to be enabled") + config.addinivalue_line("markers", "feature(name): mark a test as requiring a feature") + config.user_parameters = UserParameters(config) -def pytest_collection_modifyitems(config, items): - if is_iop_enabled(): - return - skip_iop = pytest.mark.skip(reason="IOP not enabled - skipping IOP tests ('iop' not in enabled_features)") +def pytest_collection_modifyitems(config, items): + feature_dir = config.rootdir / 'tests' / 'feature' for item in items: - if "iop" in item.keywords: - item.add_marker(skip_iop) + try: + rel_path = Path(item.fspath).relative_to(feature_dir) + except ValueError: + # Not in the features directory + pass + else: + feature = rel_path.parts[0] + # TODO: test if it's a valid feature? + item.add_marker(pytest.mark.feature(feature)) + + +def pytest_runtest_setup(item): + feature_markers = set(mark.args[0] for mark in item.iter_markers(name="feature")) + if feature_markers: + missing = feature_markers - item.config.user_parameters.features + if missing: + pytest.skip("test requires feature(s) {!r}".format(missing)) class ResolveAdapter(HTTPAdapter): diff --git a/tests/feature/__init__.py b/tests/feature/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/feature/foreman-proxy/__init__.py b/tests/feature/foreman-proxy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/foreman_proxy_test.py b/tests/feature/foreman-proxy/base_test.py similarity index 93% rename from tests/foreman_proxy_test.py rename to tests/feature/foreman-proxy/base_test.py index 847a723bb..1bb933125 100644 --- a/tests/foreman_proxy_test.py +++ b/tests/feature/foreman-proxy/base_test.py @@ -2,15 +2,10 @@ import json import pytest -from conftest import enabled_features FOREMAN_PROXY_PORT = 8443 -def is_bmc_enabled(): - return 'bmc' in enabled_features() - - def get_proxy_v2_features(server, certificates, server_fqdn): cmd = server.run( f"curl --cacert {certificates['server_ca_certificate']} " @@ -22,14 +17,14 @@ def get_proxy_v2_features(server, certificates, server_fqdn): return json.loads(cmd.stdout) -def test_foreman_proxy_features(server, certificates, server_fqdn): +def test_foreman_proxy_features(server, certificates, server_fqdn, pytestconfig): cmd = server.run(f"curl --cacert {certificates['server_ca_certificate']} --silent https://{server_fqdn}:{FOREMAN_PROXY_PORT}/features") assert cmd.succeeded features = json.loads(cmd.stdout) assert "logs" in features assert "script" in features assert "dynflow" in features - if is_bmc_enabled(): + if 'bmc' in pytestconfig.user_parameters.features: assert "bmc" in features else: assert "bmc" not in features @@ -60,7 +55,7 @@ def test_foreman_proxy_client_auth_to_foreman(server, certificates, server_fqdn) assert cmd.stdout == '201' -@pytest.mark.skipif("not is_bmc_enabled()") +@pytest.mark.feature('bmc') def test_bmc_capabilities(server, certificates, server_fqdn): features = get_proxy_v2_features(server, certificates, server_fqdn) assert 'bmc' in features diff --git a/tests/feature/foreman/__init__.py b/tests/feature/foreman/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/feature/foreman/api_test.py b/tests/feature/foreman/api_test.py new file mode 100644 index 000000000..d0f199151 --- /dev/null +++ b/tests/feature/foreman/api_test.py @@ -0,0 +1,10 @@ +def test_foreman_organization(organization): + assert organization + + +def test_foreman_initial_organization(foremanapi): + assert foremanapi.list('organizations', search='name="Foreman CI"') + + +def test_foreman_initial_location(foremanapi): + assert foremanapi.list('locations', search='name="Internet"') diff --git a/tests/foreman_test.py b/tests/feature/foreman/base_test.py similarity index 99% rename from tests/foreman_test.py rename to tests/feature/foreman/base_test.py index 174dd1f66..aa1d74ac3 100644 --- a/tests/foreman_test.py +++ b/tests/feature/foreman/base_test.py @@ -47,6 +47,7 @@ def test_foreman_status_cache(foreman_status): assert foreman_status['results']['foreman']['cache']['servers'][0]['status'] == 'ok' +@pytest.mark.feature('katello') @pytest.mark.parametrize("katello_service", ['candlepin', 'candlepin_auth', 'foreman_tasks', 'katello_events', 'pulp3', 'pulp3_content']) def test_katello_services_status(foreman_status, katello_service): assert foreman_status['results']['katello']['services'][katello_service]['status'] == 'ok' diff --git a/tests/feature/foreman/compute_resources_test.py b/tests/feature/foreman/compute_resources_test.py new file mode 100644 index 000000000..8e47bcb1f --- /dev/null +++ b/tests/feature/foreman/compute_resources_test.py @@ -0,0 +1,25 @@ +import pytest + + +# TODO: Foreman really should have a dedicated API endpoint to expose this info +@pytest.fixture +def provider_description(foremanapi): + create = foremanapi.resource('compute_resources').action('create') + compute_resource_param = [param for param in create.params if param.name == 'compute_resource'][0] + provider = [param for param in compute_resource_param.params if param.name == 'provider'][0] + return provider.description + + +@pytest.mark.parametrize("compute_resource", ['EC2', 'Libvirt', 'Openstack', 'Vmware']) +def test_foreman_compute_resources_built_in(provider_description, compute_resource): + assert compute_resource in provider_description + + +@pytest.mark.feature('azure-rm') +def test_foreman_compute_resources_azure_rm(provider_description): + assert 'AzureRm' in provider_description + + +@pytest.mark.feature('google') +def test_foreman_compute_resources_google(provider_description): + assert 'GCE' in provider_description diff --git a/tests/foreman_api_test.py b/tests/feature/foreman/katello_api_test.py similarity index 88% rename from tests/foreman_api_test.py rename to tests/feature/foreman/katello_api_test.py index 4429dbbf3..57cd2ce1b 100644 --- a/tests/foreman_api_test.py +++ b/tests/feature/foreman/katello_api_test.py @@ -1,5 +1,6 @@ -def test_foreman_organization(organization): - assert organization +import pytest + +pytestmark = pytest.mark.feature('katello') def test_foreman_product(product): @@ -49,11 +50,3 @@ def test_foreman_manifest(organization, foremanapi, fixture_dir): files = {'content': (str(manifest_path), manifest_file, 'application/zip')} params = {'organization_id': organization['id']} foremanapi.resource_action('subscriptions', 'upload', params, files=files) - - -def test_foreman_initial_organization(foremanapi): - assert foremanapi.list('organizations', search='name="Foreman CI"') - - -def test_foreman_initial_location(foremanapi): - assert foremanapi.list('locations', search='name="Internet"') diff --git a/tests/feature/foreman/plugins_test.py b/tests/feature/foreman/plugins_test.py new file mode 100644 index 000000000..d6c4c2d32 --- /dev/null +++ b/tests/feature/foreman/plugins_test.py @@ -0,0 +1,16 @@ +import pytest + + +@pytest.fixture +def foreman_plugins(foremanapi): + return [plugin['name'] for plugin in foremanapi.list('plugins')] + + +@pytest.mark.feature('azure-rm') +def test_foreman_compute_resources_azure_rm(foreman_plugins): + assert 'foreman_azure_rm' in foreman_plugins + + +@pytest.mark.feature('google') +def test_foreman_compute_resources_google(foreman_plugins): + assert 'foreman_google' in foreman_plugins diff --git a/tests/feature/hammer/__init__.py b/tests/feature/hammer/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/hammer_test.py b/tests/feature/hammer/base_test.py similarity index 100% rename from tests/hammer_test.py rename to tests/feature/hammer/base_test.py diff --git a/tests/iop/__init__.py b/tests/feature/iop/__init__.py similarity index 100% rename from tests/iop/__init__.py rename to tests/feature/iop/__init__.py diff --git a/tests/iop/test_advisor.py b/tests/feature/iop/test_advisor.py similarity index 99% rename from tests/iop/test_advisor.py rename to tests/feature/iop/test_advisor.py index 970598fd4..1d0e440bf 100644 --- a/tests/iop/test_advisor.py +++ b/tests/feature/iop/test_advisor.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_advisor_backend_api_service(server): service = server.service("iop-service-advisor-backend-api") assert service.is_running diff --git a/tests/iop/test_advisor_frontend.py b/tests/feature/iop/test_advisor_frontend.py similarity index 95% rename from tests/iop/test_advisor_frontend.py rename to tests/feature/iop/test_advisor_frontend.py index a111b61f0..c260bbaa4 100644 --- a/tests/iop/test_advisor_frontend.py +++ b/tests/feature/iop/test_advisor_frontend.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_advisor_frontend_assets_directory(server): assets_dir = server.file("/var/www/iop/assets/apps/advisor") assert assets_dir.exists diff --git a/tests/iop/test_cvemap_downloader.py b/tests/feature/iop/test_cvemap_downloader.py similarity index 97% rename from tests/iop/test_cvemap_downloader.py rename to tests/feature/iop/test_cvemap_downloader.py index b7eafc902..d16cd272d 100644 --- a/tests/iop/test_cvemap_downloader.py +++ b/tests/feature/iop/test_cvemap_downloader.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_cvemap_download_script(server): script = server.file("/usr/local/bin/iop-cvemap-download.sh") assert script.exists diff --git a/tests/iop/test_engine.py b/tests/feature/iop/test_engine.py similarity index 96% rename from tests/iop/test_engine.py rename to tests/feature/iop/test_engine.py index d2bf0aecb..99f8fd7eb 100644 --- a/tests/iop/test_engine.py +++ b/tests/feature/iop/test_engine.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_engine_service(server): service = server.service("iop-core-engine") assert service.is_running diff --git a/tests/iop/test_gateway.py b/tests/feature/iop/test_gateway.py similarity index 94% rename from tests/iop/test_gateway.py rename to tests/feature/iop/test_gateway.py index faa493851..4fc37d064 100644 --- a/tests/iop/test_gateway.py +++ b/tests/feature/iop/test_gateway.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_gateway_service(server): service = server.service("iop-core-gateway") assert service.is_running diff --git a/tests/iop/test_ingress.py b/tests/feature/iop/test_ingress.py similarity index 89% rename from tests/iop/test_ingress.py rename to tests/feature/iop/test_ingress.py index 3965cbe93..95c791d76 100644 --- a/tests/iop/test_ingress.py +++ b/tests/feature/iop/test_ingress.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_ingress_service(server): service = server.service("iop-core-ingress") assert service.is_running diff --git a/tests/iop/test_integration.py b/tests/feature/iop/test_integration.py similarity index 99% rename from tests/iop/test_integration.py rename to tests/feature/iop/test_integration.py index 8a8dacac2..6b096d8cf 100644 --- a/tests/iop/test_integration.py +++ b/tests/feature/iop/test_integration.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_iop_core_kafka_service(server): service = server.service("iop-core-kafka") assert service.is_running diff --git a/tests/iop/test_inventory.py b/tests/feature/iop/test_inventory.py similarity index 97% rename from tests/iop/test_inventory.py rename to tests/feature/iop/test_inventory.py index d69f564c5..21a2bc28e 100644 --- a/tests/iop/test_inventory.py +++ b/tests/feature/iop/test_inventory.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_inventory_migrate_service(server): service = server.service("iop-core-host-inventory-migrate") assert service.is_enabled diff --git a/tests/iop/test_inventory_frontend.py b/tests/feature/iop/test_inventory_frontend.py similarity index 95% rename from tests/iop/test_inventory_frontend.py rename to tests/feature/iop/test_inventory_frontend.py index 03af2e91d..5e4a96979 100644 --- a/tests/iop/test_inventory_frontend.py +++ b/tests/feature/iop/test_inventory_frontend.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_inventory_frontend_assets_directory(server): assets_dir = server.file("/var/www/iop/assets/apps/inventory") assert assets_dir.exists diff --git a/tests/iop/test_kafka.py b/tests/feature/iop/test_kafka.py similarity index 97% rename from tests/iop/test_kafka.py rename to tests/feature/iop/test_kafka.py index 18a859e90..b52d76c38 100644 --- a/tests/iop/test_kafka.py +++ b/tests/feature/iop/test_kafka.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_kafka_service(server): service = server.service("iop-core-kafka") assert service.is_running diff --git a/tests/iop/test_puptoo.py b/tests/feature/iop/test_puptoo.py similarity index 75% rename from tests/iop/test_puptoo.py rename to tests/feature/iop/test_puptoo.py index b5aedcd78..27ce57717 100644 --- a/tests/iop/test_puptoo.py +++ b/tests/feature/iop/test_puptoo.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_puptoo_service(server): service = server.service("iop-core-puptoo") assert service.is_running diff --git a/tests/iop/test_remediation.py b/tests/feature/iop/test_remediation.py similarity index 95% rename from tests/iop/test_remediation.py rename to tests/feature/iop/test_remediation.py index f8b609618..202ffb4d0 100644 --- a/tests/iop/test_remediation.py +++ b/tests/feature/iop/test_remediation.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_remediation_api_service(server): service = server.service("iop-service-remediations-api") assert service.is_running diff --git a/tests/iop/test_vmaas.py b/tests/feature/iop/test_vmaas.py similarity index 97% rename from tests/iop/test_vmaas.py rename to tests/feature/iop/test_vmaas.py index c7078574d..225bf9306 100644 --- a/tests/iop/test_vmaas.py +++ b/tests/feature/iop/test_vmaas.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_vmaas_reposcan_service(server): service = server.service("iop-service-vmaas-reposcan") assert service.is_running diff --git a/tests/iop/test_vulnerability.py b/tests/feature/iop/test_vulnerability.py similarity index 99% rename from tests/iop/test_vulnerability.py rename to tests/feature/iop/test_vulnerability.py index 8380921fe..a409acc17 100644 --- a/tests/iop/test_vulnerability.py +++ b/tests/feature/iop/test_vulnerability.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_vulnerability_manager_service(server): service = server.service("iop-service-vuln-manager") assert service.is_running diff --git a/tests/iop/test_vulnerability_frontend.py b/tests/feature/iop/test_vulnerability_frontend.py similarity index 95% rename from tests/iop/test_vulnerability_frontend.py rename to tests/feature/iop/test_vulnerability_frontend.py index 4b55af898..8f6172bb7 100644 --- a/tests/iop/test_vulnerability_frontend.py +++ b/tests/feature/iop/test_vulnerability_frontend.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_vulnerability_frontend_assets_directory(server): assets_dir = server.file("/var/www/iop/assets/apps/vulnerability") assert assets_dir.exists diff --git a/tests/iop/test_yuptoo.py b/tests/feature/iop/test_yuptoo.py similarity index 75% rename from tests/iop/test_yuptoo.py rename to tests/feature/iop/test_yuptoo.py index 85fcd411a..3acc0ace3 100644 --- a/tests/iop/test_yuptoo.py +++ b/tests/feature/iop/test_yuptoo.py @@ -1,8 +1,3 @@ -import pytest - -pytestmark = pytest.mark.iop - - def test_yuptoo_service(server): service = server.service("iop-core-yuptoo") assert service.is_running diff --git a/tests/feature/katello/__init__.py b/tests/feature/katello/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/candlepin_test.py b/tests/feature/katello/candlepin_test.py similarity index 95% rename from tests/candlepin_test.py rename to tests/feature/katello/candlepin_test.py index bfdf731c8..ae81bb5b7 100644 --- a/tests/candlepin_test.py +++ b/tests/feature/katello/candlepin_test.py @@ -1,3 +1,8 @@ +import pytest + +pytestmark = pytest.mark.feature("foreman") + + def assert_secret_content(server, secret_name, secret_value): secret = server.run(f'podman secret inspect --format {"{{.SecretData}}"} --showsecret {secret_name}') assert secret.succeeded diff --git a/tests/client_test.py b/tests/feature/katello/client_test.py similarity index 100% rename from tests/client_test.py rename to tests/feature/katello/client_test.py diff --git a/tests/pulp_test.py b/tests/feature/katello/pulp_test.py similarity index 100% rename from tests/pulp_test.py rename to tests/feature/katello/pulp_test.py diff --git a/tests/features_test.py b/tests/features_test.py index 70cb23935..0fe3c99f2 100644 --- a/tests/features_test.py +++ b/tests/features_test.py @@ -1,5 +1,7 @@ import subprocess +import pytest + def test_foremanctl_features(): command = ['./foremanctl', 'features'] @@ -24,6 +26,7 @@ def test_foremanctl_features_list_enabled(): assert 'available' not in result.stdout +@pytest.mark.disruptive def test_invalid_feature_rejected(): command = ['./foremanctl', 'deploy', '--add-feature', 'invalid-feature'] result = subprocess.run(command, capture_output=True, text=True) diff --git a/tests/foreman_compute_resources_test.py b/tests/foreman_compute_resources_test.py deleted file mode 100644 index fc5f985bf..000000000 --- a/tests/foreman_compute_resources_test.py +++ /dev/null @@ -1,11 +0,0 @@ -import pytest - -FOREMAN_HOST = 'localhost' -FOREMAN_PORT = 3000 - - -@pytest.mark.parametrize("compute_resource", ['AzureRm', 'EC2', 'GCE', 'Libvirt', 'Openstack', 'Vmware']) -def test_foreman_compute_resources(server, compute_resource): - hammer = server.run("hammer compute-resource create --help | grep provider") - assert hammer.succeeded - assert compute_resource in hammer.stdout diff --git a/tests/foreman_plugins_test.py b/tests/foreman_plugins_test.py deleted file mode 100644 index b2c787ccb..000000000 --- a/tests/foreman_plugins_test.py +++ /dev/null @@ -1,7 +0,0 @@ -import pytest - - -@pytest.mark.parametrize("foreman_plugin", ['foreman_azure_rm', 'foreman_google']) -def test_foreman_compute_resources(foremanapi, foreman_plugin): - plugins = [plugin['name'] for plugin in foremanapi.list('plugins')] - assert foreman_plugin in plugins diff --git a/tests/httpd_test.py b/tests/httpd_test.py index fe07d2d4d..796939ac5 100644 --- a/tests/httpd_test.py +++ b/tests/httpd_test.py @@ -1,3 +1,5 @@ +import pytest + HTTP_HOST = 'localhost' HTTP_PORT = 80 HTTPS_PORT = 443 @@ -21,48 +23,56 @@ def test_https_port(server): assert httpd.port(HTTPS_PORT).is_reachable +@pytest.mark.feature("foreman") def test_http_foreman_ping(server, server_fqdn): cmd = server.run(f"{CURL_CMD} --write-out '%{{redirect_url}}' http://{server_fqdn}/api/v2/ping") assert cmd.succeeded assert cmd.stdout == f'https://{server_fqdn}/api/v2/ping' +@pytest.mark.feature("foreman") def test_https_foreman_ping(server, certificates, server_fqdn): cmd = server.run(f"{CURL_CMD} --cacert {certificates['server_ca_certificate']} --write-out '%{{http_code}}' https://{server_fqdn}/api/v2/ping") assert cmd.succeeded assert cmd.stdout == '200' +@pytest.mark.feature("katello") def test_http_pulp_api_status(server, server_fqdn): cmd = server.run(f"{CURL_CMD} --write-out '%{{http_code}}' http://{server_fqdn}/pulp/api/v3/status/") assert cmd.succeeded assert cmd.stdout == '404' +@pytest.mark.feature("katello") def test_https_pulp_api_status(server, certificates, server_fqdn): cmd = server.run(f"{CURL_CMD} --cacert {certificates['server_ca_certificate']} --write-out '%{{http_code}}' https://{server_fqdn}/pulp/api/v3/status/") assert cmd.succeeded assert cmd.stdout == '200' +@pytest.mark.feature("katello") def test_http_pulp_content(server, server_fqdn): cmd = server.run(f"{CURL_CMD} --write-out '%{{stderr}}%{{http_code}}' http://{server_fqdn}/pulp/content/") assert cmd.succeeded assert cmd.stderr == '200' +@pytest.mark.feature("katello") def test_https_pulp_content(server, certificates, server_fqdn): cmd = server.run(f"curl --silent --cacert {certificates['server_ca_certificate']} https://{server_fqdn}/pulp/content/") assert cmd.succeeded assert "Index of /pulp/content/" in cmd.stdout +@pytest.mark.feature("katello") def test_https_pulp_auth(server, certificates, server_fqdn): cmd = server.run(f"{CURL_CMD} --cacert {certificates['server_ca_certificate']} --write-out '%{{http_code}}' --cert {certificates['client_certificate']} --key {certificates['client_key']} https://{server_fqdn}/pulp/api/v3/users/") assert cmd.succeeded assert cmd.stdout == '200' +@pytest.mark.feature("katello") def test_https_pypi_endpoint(server, certificates, server_fqdn): cmd = server.run(f"curl --cacert {certificates['server_ca_certificate']} https://{server_fqdn}/pypi/test/") assert cmd.succeeded @@ -102,12 +112,14 @@ def test_https_pub_server_ca_certificate_downloadable(server, certificates, serv assert cmd.stdout == '200' +@pytest.mark.feature("foreman") def test_http_foreman_login(server, server_fqdn): cmd = server.run(f"{CURL_CMD} --write-out '%{{http_code}}' http://{server_fqdn}/users/login") assert cmd.succeeded assert cmd.stdout == '301' +@pytest.mark.feature("foreman") def test_https_foreman_login(server, certificates, server_fqdn): cmd = server.run(f"{CURL_CMD} --cacert {certificates['server_ca_certificate']} --write-out '%{{http_code}}' https://{server_fqdn}/users/login") assert cmd.succeeded diff --git a/tests/postgresql_test.py b/tests/postgresql_test.py index 82187466a..42fdaa7c8 100644 --- a/tests/postgresql_test.py +++ b/tests/postgresql_test.py @@ -13,18 +13,38 @@ def test_postgresql_port(database): assert postgresql.port("5432").is_reachable -def test_postgresql_databases(database): +def test_postgresql_databases(features, database): result = database.run("podman exec postgresql psql -U postgres -c '\\l'") - assert "foreman" in result.stdout - assert "candlepin" in result.stdout - assert "pulp" in result.stdout + + if "foreman" in features: + assert "foreman" in result.stdout + else: + assert "foreman" not in result.stdout + + if "katello" in features: + if "foreman" in features: + assert "candlepin" in result.stdout + assert "pulp" in result.stdout + else: + assert "candlepin" not in result.stdout + assert "pulp" not in result.stdout -def test_postgresql_users(database): +def test_postgresql_users(features, database): result = database.run("podman exec postgresql psql -U postgres -c '\\du'") - assert "foreman" in result.stdout - assert "candlepin" in result.stdout - assert "pulp" in result.stdout + + if "foreman" in features: + assert "foreman" in result.stdout + else: + assert "foreman" not in result.stdout + + if "katello" in features: + if "foreman" in features: + assert "candlepin" in result.stdout + assert "pulp" in result.stdout + else: + assert "candlepin" not in result.stdout + assert "pulp" not in result.stdout def test_postgresql_password_encryption(database): diff --git a/tests/target_lifecycle_test.py b/tests/target_lifecycle_test.py index f834ffc97..83cc34df3 100644 --- a/tests/target_lifecycle_test.py +++ b/tests/target_lifecycle_test.py @@ -1,5 +1,7 @@ import time +import pytest + FOREMAN_PING_RETRIES = 60 FOREMAN_PING_DELAY = 10 CURL_CMD = "curl --silent --output /dev/null" @@ -18,6 +20,7 @@ def _wait_for_foreman(server, server_fqdn, certificates): raise AssertionError("Foreman did not become available after target lifecycle operation") +@pytest.mark.disruptive def test_foreman_target_stop_start(server, server_fqdn, certificates): result = server.run("systemctl stop foreman.target") assert result.rc == 0, f"Failed to stop foreman.target: {result.stderr}" @@ -29,6 +32,7 @@ def test_foreman_target_stop_start(server, server_fqdn, certificates): assert server.service("foreman.target").is_running +@pytest.mark.disruptive def test_foreman_target_restart(server, server_fqdn, certificates): result = server.run("systemctl restart foreman.target") assert result.rc == 0, f"Failed to restart foreman.target: {result.stderr}"