From 556c409e4ec6bb662f989acfa8302d30aa4c4115 Mon Sep 17 00:00:00 2001 From: Amy Chen Date: Fri, 13 Mar 2026 14:16:16 +0800 Subject: [PATCH] test: fix integration test_combined for rhel integraton tests: add RHEL distro support - add default usename for RHEL distro and platform specific. - add optional LAUNCH_USERNAME in integration_settings to override default username per run. - use distro-specific USER_DATA in test_combined and adjust rsyslog and locale config so they work on RHEL, and removing the modules which not support RHEL. - skip the tests in test_combined which do not surport RHEL. Signed-off-by: Amy Chen --- tests/integration_tests/clouds.py | 23 +++- .../integration_tests/integration_settings.py | 4 + .../modules/test_combined.py | 127 +++++++++++++++--- tests/integration_tests/releases.py | 4 + 4 files changed, 136 insertions(+), 22 deletions(-) diff --git a/tests/integration_tests/clouds.py b/tests/integration_tests/clouds.py index e72213a1002..3ccb06e104b 100644 --- a/tests/integration_tests/clouds.py +++ b/tests/integration_tests/clouds.py @@ -39,8 +39,24 @@ DISTRO_TO_USERNAME = { "ubuntu": "ubuntu", + "rhel": "cloud-user", + "centos": "cloud-user", } +# Platform specific username overrides: (distro, platform) -> username +# Only list entries where the platform differs from the distro default. +DISTRO_PLATFORM_TO_USERNAME = { + ("rhel", "ec2"): integration_settings.LAUNCH_USERNAME or "ec2-user", + ("rhel", "azure"): integration_settings.LAUNCH_USERNAME or "azureuser", +} + + +def get_launch_username(os: str, platform: str) -> str: + key = (os, platform) + if key in DISTRO_PLATFORM_TO_USERNAME: + return DISTRO_PLATFORM_TO_USERNAME[key] + return DISTRO_TO_USERNAME[os] + def _get_ubuntu_series() -> list: """Use distro-info-data's ubuntu.csv to get a list of Ubuntu series""" @@ -135,7 +151,9 @@ def launch( default_launch_kwargs = { "image_id": self.image_id, "user_data": user_data, - "username": DISTRO_TO_USERNAME[CURRENT_RELEASE.os], + "username": get_launch_username( + CURRENT_RELEASE.os, self.datasource + ), } if self.settings.INSTANCE_TYPE: default_launch_kwargs["instance_type"] = ( @@ -259,9 +277,10 @@ def _get_initial_image(self, **kwargs) -> str: class AzureCloud(IntegrationCloud): datasource = "azure" cloud_instance: Azure + username = get_launch_username(CURRENT_RELEASE.os, datasource) def _get_cloud_instance(self) -> Azure: - return Azure(tag="azure-integration-test") + return Azure(tag="azure-integration-test", username=self.username) def _get_initial_image(self, **kwargs) -> str: return super()._get_initial_image( diff --git a/tests/integration_tests/integration_settings.py b/tests/integration_tests/integration_settings.py index cb4bae3a84e..6164b4e7332 100644 --- a/tests/integration_tests/integration_settings.py +++ b/tests/integration_tests/integration_settings.py @@ -56,6 +56,10 @@ # creating a new one. The exact contents will be platform dependent EXISTING_INSTANCE_ID: Optional[str] = None +# Username to use when launching the instance. +# If not set, the default username for the platform will be used. +LAUNCH_USERNAME: Optional[str] = None + ################################################################## # IMAGE GENERATION SETTINGS ################################################################## diff --git a/tests/integration_tests/modules/test_combined.py b/tests/integration_tests/modules/test_combined.py index 857023780d1..ec3962f0738 100644 --- a/tests/integration_tests/modules/test_combined.py +++ b/tests/integration_tests/modules/test_combined.py @@ -26,7 +26,12 @@ OS_IMAGE_TYPE, PLATFORM, ) -from tests.integration_tests.releases import CURRENT_RELEASE, IS_UBUNTU, NOBLE +from tests.integration_tests.releases import ( + CURRENT_RELEASE, + IS_RHEL, + IS_UBUNTU, + NOBLE, +) from tests.integration_tests.util import ( get_feature_flag_value, get_inactive_modules, @@ -37,7 +42,7 @@ verify_ordered_items_in_text, ) -USER_DATA = """\ +USER_DATA_UBUNTU = """\ #cloud-config users: - default @@ -90,6 +95,61 @@ timezone: Europe/Madrid """ +USER_DATA_RHEL = """\ +#cloud-config +users: +- default +- name: craig + sudo: false # make sure craig doesn't get elevated perms +final_message: | + This is my final message! + $version + $timestamp + $datasource + $uptime +locale: en_GB.UTF-8 +locale_configfile: /etc/locale.conf +package_update: true +random_seed: + data: 'MYUb34023nD:LFDK10913jk;dfnk:Df' + encoding: raw + file: /root/seed +rsyslog: + configs: + - "*.* @@127.0.0.1" + - filename: 0-basic-config.conf + content: | + module(load="imtcp") + input(type="imtcp" port="514") + $template RemoteLogs,"/var/log/rsyslog-cloudinit.log" + *.* ?RemoteLogs + & ~ + remotes: + me: "127.0.0.1" +runcmd: + - echo 'hello world' > /var/tmp/runcmd_output + - echo '💩' > /var/tmp/unicode_data + + - # + - logger "My test log" + +timezone: Europe/Madrid +""" +# Update this dict with proper user data to support new distros +USER_DATA_BY_DISTRO = { + "ubuntu": USER_DATA_UBUNTU, + "rhel": USER_DATA_RHEL, + "centos": USER_DATA_RHEL, +} + +if CURRENT_RELEASE.os not in USER_DATA_BY_DISTRO: + raise KeyError( + f"No USER_DATA for distro {CURRENT_RELEASE.os!r}. " + f"Add an entry to USER_DATA_BY_DISTRO for this distro." + ) + +USER_DATA = USER_DATA_BY_DISTRO[CURRENT_RELEASE.os] + @pytest.mark.ci @pytest.mark.user_data(USER_DATA) @@ -163,6 +223,7 @@ def test_deprecated_message(self, class_client: IntegrationInstance): ignore_warnings=True, ) + @pytest.mark.skipif(IS_RHEL, reason="rhel does not support ntp module") def test_ntp_with_apt(self, class_client: IntegrationInstance): """LP #1628337. @@ -175,6 +236,9 @@ def test_ntp_with_apt(self, class_client: IntegrationInstance): assert "W: Some index files failed to download" not in log assert "E: Unable to locate package ntp" not in log + @pytest.mark.skipif( + IS_RHEL, reason="rhel does not enable byobu by default" + ) def test_byobu(self, class_client: IntegrationInstance): """Test byobu configured as enabled by default.""" client = class_client @@ -183,9 +247,13 @@ def test_byobu(self, class_client: IntegrationInstance): def test_configured_locale(self, class_client: IntegrationInstance): """Test locale can be configured correctly.""" client = class_client - default_locale = client.read_from_file("/etc/default/locale") + default_locale_file = ( + "/etc/locale.conf" if IS_RHEL else "/etc/default/locale" + ) + default_locale = client.read_from_file(default_locale_file) assert "LANG=en_GB.UTF-8" in default_locale - + if IS_RHEL: + return locale_a = client.execute("locale -a") locale_gen = client.execute("grep -v '^#' /etc/locale.gen | uniq") if OS_IMAGE_TYPE == "minimal": @@ -214,16 +282,21 @@ def test_random_seed_data(self, class_client: IntegrationInstance): def test_rsyslog(self, class_client: IntegrationInstance): """Test rsyslog is configured correctly when applicable.""" + # /var/spool/rsylog is not created on rhel by default + log_file = ( + "/var/log/rsyslog-cloudinit.log" + if IS_RHEL + else "/var/spool/rsyslog/cloudinit.log" + ) if class_client.execute("command -v rsyslogd").ok: - assert "My test log" in class_client.read_from_file( - "/var/spool/rsyslog/cloudinit.log" - ) + assert "My test log" in class_client.read_from_file(log_file) def test_runcmd(self, class_client: IntegrationInstance): """Test runcmd works as expected""" client = class_client assert "hello world" == client.read_from_file("/var/tmp/runcmd_output") + @pytest.mark.skipif(IS_RHEL, reason="rhel does not support snap module") def test_snap(self, class_client: IntegrationInstance): """Integration test for the snap module. @@ -276,19 +349,32 @@ def test_no_problems(self, class_client: IntegrationInstance): verify_clean_boot( client, ignore_deprecations=True, require_warnings=require_warnings ) - requested_modules = { - "apt_configure", - "byobu", - "final_message", - "locale", - "ntp", - "seed_random", - "rsyslog", - "runcmd", - "snap", - "ssh_import_id", - "timezone", - } + # remove modules that are not supported on rhel + requested_modules = ( + { + "byobu", + "final_message", + "locale", + "seed_random", + "rsyslog", + "runcmd", + "timezone", + } + if IS_RHEL + else { + "apt_configure", + "byobu", + "final_message", + "locale", + "ntp", + "seed_random", + "rsyslog", + "runcmd", + "snap", + "ssh_import_id", + "timezone", + } + ) inactive_modules = get_inactive_modules(log) assert not requested_modules.intersection(inactive_modules), ( f"Expected active modules:" @@ -578,6 +664,7 @@ def test_networkd_wait_online(self, class_client: IntegrationInstance): @pytest.mark.user_data(USER_DATA) class TestCombinedNoCI: @retry(tries=30, delay=1) + @pytest.mark.skipif(IS_RHEL, reason="rhel skips ssh_import_id module") def test_ssh_import_id(self, class_client: IntegrationInstance): """Integration test for the ssh_import_id module. diff --git a/tests/integration_tests/releases.py b/tests/integration_tests/releases.py index 3c3c1fd3df0..25ca759f8e3 100644 --- a/tests/integration_tests/releases.py +++ b/tests/integration_tests/releases.py @@ -105,3 +105,7 @@ def from_os_image( CURRENT_RELEASE = Release.from_os_image() IS_UBUNTU = CURRENT_RELEASE.os == "ubuntu" +IS_RHEL = CURRENT_RELEASE.os in ( + "rhel", + "centos", +) # will add other RHEL-like distros later