From 96a6314164f90005249bc7a0877887370d608299 Mon Sep 17 00:00:00 2001 From: Cole Higgins Date: Mon, 6 Jul 2026 16:58:47 -0400 Subject: [PATCH 1/4] update iop for foremanctl --- robottelo/host_helpers/satellite_mixins.py | 64 +++++++++++---------- robottelo/hosts.py | 7 ++- tests/foreman/cli/test_rhcloud_iop.py | 65 ++++++++++++++-------- 3 files changed, 85 insertions(+), 51 deletions(-) diff --git a/robottelo/host_helpers/satellite_mixins.py b/robottelo/host_helpers/satellite_mixins.py index 545fc54f90f..7f23e59dc6c 100644 --- a/robottelo/host_helpers/satellite_mixins.py +++ b/robottelo/host_helpers/satellite_mixins.py @@ -21,7 +21,7 @@ PUPPET_COMMON_INSTALLER_OPTS, PUPPET_SATELLITE_INSTALLER, ) -from robottelo.enums import NetworkType +from robottelo.enums import InstallMethod, NetworkType from robottelo.exceptions import CLIReturnCodeError, NoManifestProvidedError, SatelliteHostError from robottelo.host_helpers.api_factory import APIFactory from robottelo.host_helpers.cli_factory import CLIFactory @@ -457,7 +457,11 @@ def get_iop_image_paths(): } def configure_iop(self): - """Configure on prem Advisor engine on Satellite""" + """Configure on prem Advisor engine on Satellite. + + Branches on install_method: foremanctl uses ``foremanctl deploy --add-feature iop``, + installer uses ``satellite-installer --enable-iop --iop-ensure present``. + """ logger.info('Configuring Satellite with local Red Hat Lightspeed') self.register_to_cdn() @@ -472,30 +476,33 @@ def configure_iop(self): iop_settings.stage_username, iop_settings.stage_token, iop_settings.stage_registry ) - # Set IPv6 podman proxy on Satellite, to pull from container registry self.enable_ipv6_podman_proxy() - # Set up container image path overrides - if image_paths := self.get_iop_image_paths(): - custom_hiera = f'{robottelo_tmp_dir}/custom-hiera.yaml' - - with open(custom_hiera, 'w') as f: - yaml.dump( - image_paths, - f, - sort_keys=False, - default_flow_style=False, - ) - self.put(custom_hiera, '/etc/foreman-installer/custom-hiera.yaml') - - command = InstallerCommand( - 'enable-iop', - iop_ensure='present', - scenario='satellite', - foreman_initial_admin_password=settings.server.admin_password, - ).get_command() - - result = self.execute(command, timeout='30m') + if self.install_method == InstallMethod.FOREMANCTL: + result = self.execute('foremanctl deploy --add-feature iop', timeout='30m') + else: + # Set up container image path overrides for satellite-installer + if image_paths := self.get_iop_image_paths(): + custom_hiera = f'{robottelo_tmp_dir}/custom-hiera.yaml' + + with open(custom_hiera, 'w') as f: + yaml.dump( + image_paths, + f, + sort_keys=False, + default_flow_style=False, + ) + self.put(custom_hiera, '/etc/foreman-installer/custom-hiera.yaml') + + command = InstallerCommand( + 'enable-iop', + iop_ensure='present', + scenario='satellite', + foreman_initial_admin_password=settings.server.admin_password, + ).get_command() + + result = self.execute(command, timeout='30m') + if result.status != 0: raise SatelliteHostError(f'Failed to configure IoP: {result.stdout}') if not self.iop_enabled: @@ -506,11 +513,12 @@ def uninstall_iop(self): logger.info('IoP is already disabled. Skipping uninstallation.') return - command = InstallerCommand( - iop_ensure='absent', - ).get_command() + if self.install_method == InstallMethod.FOREMANCTL: + result = self.execute('foremanctl deploy --remove-feature iop', timeout='30m') + else: + command = InstallerCommand(iop_ensure='absent').get_command() + result = self.execute(command, timeout='30m') - result = self.execute(command, timeout='30m') if result.status != 0: raise SatelliteHostError(f'Failed to disable IoP: {result.stdout}') if self.iop_enabled: diff --git a/robottelo/hosts.py b/robottelo/hosts.py index 9fab16fb85f..44140de35c8 100644 --- a/robottelo/hosts.py +++ b/robottelo/hosts.py @@ -3150,7 +3150,12 @@ def set_pulp_cli_safemode(self, safe): @property def iop_enabled(self): """Return boolean indicating whether IoP (local Red Hat Lightspeed) is enabled.""" - return self.api.RHCloud().advisor_engine_config()['use_iop_mode'] + from robottelo.enums import InstallMethod + + if self.install_method == InstallMethod.FOREMANCTL: + return 'iop' in self.list_foremanctl_features(enabled=True) + result = self.execute('systemctl is-active iop-core-engine') + return result.status == 0 class SSOHost(Host): diff --git a/tests/foreman/cli/test_rhcloud_iop.py b/tests/foreman/cli/test_rhcloud_iop.py index a3283efce35..122168581bc 100644 --- a/tests/foreman/cli/test_rhcloud_iop.py +++ b/tests/foreman/cli/test_rhcloud_iop.py @@ -16,6 +16,7 @@ import yaml from robottelo.config import settings +from robottelo.enums import InstallMethod from robottelo.utils.installer import InstallerCommand IOP_SERVICES = [ @@ -113,24 +114,33 @@ def test_positive_install_iop_custom_certs( ) assert result.status == 0, f'Error logging in to container registry: {result.stdout}' - # Set up container image path overrides - custom_hiera_yaml = yaml.dump( - {f'iop::{service}::image': path for service, path in iop_settings.image_paths.items()} - ) - satellite.execute(f'echo "{custom_hiera_yaml}" > /etc/foreman-installer/custom-hiera.yaml') - - command = InstallerCommand( - 'enable-iop', - 'certs-update-server', - 'certs-update-server-ca', - scenario='satellite', - certs_server_cert=f'/root/{certs_data["cert_file_name"]}', - certs_server_key=f'/root/{certs_data["key_file_name"]}', - certs_server_ca_cert=f'/root/{certs_data["ca_bundle_file_name"]}', - foreman_initial_admin_password=settings.server.admin_password, - ).get_command() - - result = satellite.execute(command, timeout='30m') + if satellite.install_method == InstallMethod.FOREMANCTL: + result = satellite.execute( + 'foremanctl deploy --add-feature iop' + f' --certificate-source=custom_server' + f' --certificate-server-certificate /root/{certs_data["cert_file_name"]}' + f' --certificate-server-key /root/{certs_data["key_file_name"]}', + timeout='30m', + ) + else: + # Set up container image path overrides + custom_hiera_yaml = yaml.dump( + {f'iop::{service}::image': path for service, path in iop_settings.image_paths.items()} + ) + satellite.execute(f'echo "{custom_hiera_yaml}" > /etc/foreman-installer/custom-hiera.yaml') + + command = InstallerCommand( + 'enable-iop', + 'certs-update-server', + 'certs-update-server-ca', + scenario='satellite', + certs_server_cert=f'/root/{certs_data["cert_file_name"]}', + certs_server_key=f'/root/{certs_data["key_file_name"]}', + certs_server_ca_cert=f'/root/{certs_data["ca_bundle_file_name"]}', + foreman_initial_admin_password=settings.server.admin_password, + ).get_command() + + result = satellite.execute(command, timeout='30m') assert result.status == 0 result = satellite.execute('hammer ping') @@ -222,8 +232,11 @@ def test_disable_enable_iop(module_satellite_iop, module_sca_manifest, rhel_cont assert result.status == 0, 'Initial insights-client upload failed' # Disable IoP - command = InstallerCommand(iop_ensure='absent').get_command() - result = satellite.execute(command, timeout='10m') + if satellite.install_method == InstallMethod.FOREMANCTL: + result = satellite.execute('foremanctl deploy --remove-feature iop', timeout='30m') + else: + command = InstallerCommand(iop_ensure='absent').get_command() + result = satellite.execute(command, timeout='10m') assert result.status == 0, 'Failed to disable IoP' result = satellite.execute('satellite-maintain service restart') @@ -260,8 +273,11 @@ def test_disable_enable_iop(module_satellite_iop, module_sca_manifest, rhel_cont assert result.status == 0, 'Failed to unregister from Red Hat Lightspeed' # Re-enable IoP - command = InstallerCommand(iop_ensure='present').get_command() - result = satellite.execute(command, timeout='10m') + if satellite.install_method == InstallMethod.FOREMANCTL: + result = satellite.execute('foremanctl deploy --add-feature iop', timeout='30m') + else: + command = InstallerCommand(iop_ensure='present').get_command() + result = satellite.execute(command, timeout='10m') assert result.status == 0, 'Failed to re-enable IoP' result = satellite.execute('satellite-maintain service restart') @@ -369,6 +385,11 @@ def test_set_iop_log_level_via_installer(module_satellite_iop): :Verifies: SAT-41750 """ + if module_satellite_iop.install_method == InstallMethod.FOREMANCTL: + pytest.skip( + 'IoP log level configuration via satellite-installer not available on foremanctl' + ) + NEW_LOG_LEVEL = 'DEBUG' # Retrieve the IoP log level settings from satellite-installer help output From bd940aaa98448635d011cdb6ff6ac3118f09abaa Mon Sep 17 00:00:00 2001 From: Cole Higgins Date: Tue, 14 Jul 2026 15:46:30 -0400 Subject: [PATCH 2/4] move import and update docstring --- robottelo/host_helpers/satellite_mixins.py | 2 +- robottelo/hosts.py | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/robottelo/host_helpers/satellite_mixins.py b/robottelo/host_helpers/satellite_mixins.py index 7f23e59dc6c..93e86a9d317 100644 --- a/robottelo/host_helpers/satellite_mixins.py +++ b/robottelo/host_helpers/satellite_mixins.py @@ -459,7 +459,7 @@ def get_iop_image_paths(): def configure_iop(self): """Configure on prem Advisor engine on Satellite. - Branches on install_method: foremanctl uses ``foremanctl deploy --add-feature iop``, + Based on install_method: foremanctl uses ``foremanctl deploy --add-feature iop``, installer uses ``satellite-installer --enable-iop --iop-ensure present``. """ logger.info('Configuring Satellite with local Red Hat Lightspeed') diff --git a/robottelo/hosts.py b/robottelo/hosts.py index 44140de35c8..050b45982f2 100644 --- a/robottelo/hosts.py +++ b/robottelo/hosts.py @@ -54,7 +54,7 @@ RHSSO_USER_UPDATE, SATELLITE_VERSION, ) -from robottelo.enums import NetworkType +from robottelo.enums import InstallMethod, NetworkType from robottelo.exceptions import ( CapsuleHostError, CLIFactoryError, @@ -1805,7 +1805,6 @@ def detect_install_method(self): :return: InstallMethod enum value :rtype: InstallMethod """ - from robottelo.enums import InstallMethod # Runtime override if hasattr(self, '_install_method_override'): @@ -1855,7 +1854,6 @@ def get_service_names(self): :rtype: list """ from robottelo.constants import InstallationServices - from robottelo.enums import InstallMethod if self.install_method == InstallMethod.FOREMANCTL: return InstallationServices.FOREMANCTL_SERVICES @@ -2268,7 +2266,6 @@ def install_satellite( :param foremanctl_parameters: Parameters list for foremanctl deploy :return: Installation result """ - from robottelo.enums import InstallMethod from robottelo.utils.installer import InstallerCommand # Determine method @@ -3150,7 +3147,6 @@ def set_pulp_cli_safemode(self, safe): @property def iop_enabled(self): """Return boolean indicating whether IoP (local Red Hat Lightspeed) is enabled.""" - from robottelo.enums import InstallMethod if self.install_method == InstallMethod.FOREMANCTL: return 'iop' in self.list_foremanctl_features(enabled=True) From de25fb9d3228e00b6e1931450251d5463dfb8fcc Mon Sep 17 00:00:00 2001 From: Cole Higgins Date: Wed, 15 Jul 2026 09:35:19 -0400 Subject: [PATCH 3/4] add image path and cert override --- robottelo/host_helpers/satellite_mixins.py | 6 ++++++ tests/foreman/cli/test_rhcloud_iop.py | 14 +++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/robottelo/host_helpers/satellite_mixins.py b/robottelo/host_helpers/satellite_mixins.py index 93e86a9d317..03385495789 100644 --- a/robottelo/host_helpers/satellite_mixins.py +++ b/robottelo/host_helpers/satellite_mixins.py @@ -479,6 +479,12 @@ def configure_iop(self): self.enable_ipv6_podman_proxy() if self.install_method == InstallMethod.FOREMANCTL: + for service, image in settings.rh_cloud.iop.image_paths.items(): + quadlet_name = f'iop-{service.replace("_", "-")}' + self.execute( + f"sed -i 's|^Image=.*|Image={image}|' " + f"/etc/containers/systemd/{quadlet_name}.image" + ) result = self.execute('foremanctl deploy --add-feature iop', timeout='30m') else: # Set up container image path overrides for satellite-installer diff --git a/tests/foreman/cli/test_rhcloud_iop.py b/tests/foreman/cli/test_rhcloud_iop.py index 122168581bc..dffbcb6484b 100644 --- a/tests/foreman/cli/test_rhcloud_iop.py +++ b/tests/foreman/cli/test_rhcloud_iop.py @@ -115,11 +115,18 @@ def test_positive_install_iop_custom_certs( assert result.status == 0, f'Error logging in to container registry: {result.stdout}' if satellite.install_method == InstallMethod.FOREMANCTL: + for service, image in iop_settings.image_paths.items(): + quadlet_name = f'iop-{service.replace("_", "-")}' + satellite.execute( + f"sed -i 's|^Image=.*|Image={image}|' " + f"/etc/containers/systemd/{quadlet_name}.image" + ) result = satellite.execute( 'foremanctl deploy --add-feature iop' f' --certificate-source=custom_server' f' --certificate-server-certificate /root/{certs_data["cert_file_name"]}' - f' --certificate-server-key /root/{certs_data["key_file_name"]}', + f' --certificate-server-key /root/{certs_data["key_file_name"]}' + f' --certificate-server-ca-certificate /root/{certs_data["ca_bundle_file_name"]}', timeout='30m', ) else: @@ -368,6 +375,7 @@ def process_iop_log_options(installer_output): return options_dict +@pytest.mark.foreman_installer def test_set_iop_log_level_via_installer(module_satellite_iop): """Set IoP log level to DEBUG using satellite-installer options. @@ -385,10 +393,6 @@ def test_set_iop_log_level_via_installer(module_satellite_iop): :Verifies: SAT-41750 """ - if module_satellite_iop.install_method == InstallMethod.FOREMANCTL: - pytest.skip( - 'IoP log level configuration via satellite-installer not available on foremanctl' - ) NEW_LOG_LEVEL = 'DEBUG' From 89cf6a4ed5c15b017a887feb68bc834e4c56807a Mon Sep 17 00:00:00 2001 From: Cole Higgins Date: Wed, 15 Jul 2026 09:37:16 -0400 Subject: [PATCH 4/4] precommit --- tests/foreman/cli/test_rhcloud_iop.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/foreman/cli/test_rhcloud_iop.py b/tests/foreman/cli/test_rhcloud_iop.py index dffbcb6484b..f99d0bfa53d 100644 --- a/tests/foreman/cli/test_rhcloud_iop.py +++ b/tests/foreman/cli/test_rhcloud_iop.py @@ -118,8 +118,7 @@ def test_positive_install_iop_custom_certs( for service, image in iop_settings.image_paths.items(): quadlet_name = f'iop-{service.replace("_", "-")}' satellite.execute( - f"sed -i 's|^Image=.*|Image={image}|' " - f"/etc/containers/systemd/{quadlet_name}.image" + f"sed -i 's|^Image=.*|Image={image}|' /etc/containers/systemd/{quadlet_name}.image" ) result = satellite.execute( 'foremanctl deploy --add-feature iop'