Skip to content

Commit

Permalink
Adding EULA acceptance: Addressing PR feedback #1
Browse files Browse the repository at this point in the history
  • Loading branch information
rane-rajasi committed Sep 11, 2023
1 parent 455334d commit a271126
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 53 deletions.
60 changes: 57 additions & 3 deletions src/core/src/bootstrap/ConfigurationFactory.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

""" Configure factory. This module populates configuration based on package manager and environment, e.g. TEST/DEV/PROD"""
from __future__ import print_function

import json
import os
import time
from core.src.bootstrap.Constants import Constants
Expand Down Expand Up @@ -91,16 +93,16 @@ def get_bootstrap_configuration(self, env):
configuration_key = str.lower('{0}_config'.format(str(env)))
return self.bootstrap_configurations[configuration_key]

@staticmethod
def get_arguments_configuration(argv):
def get_arguments_configuration(self, argv):
""" Composes the configuration with the passed in arguments. """
arguments_config = {
'execution_arguments': str(argv),
'execution_config': {
'component': ExecutionConfig,
'component_args': ['env_layer', 'composite_logger'],
'component_kwargs': {
'execution_parameters': str(argv)
'execution_parameters': str(argv),
'accept_package_eula': self.accept_package_eula(),
}
}
}
Expand Down Expand Up @@ -298,4 +300,56 @@ def get_vm_cloud_type():
else:
print("Failed to connect IMDS end point after 5 retries. This is expected in Arc VMs. VMCloudType is set to Arc.\n")
return Constants.VMCloudType.ARC

def accept_package_eula(self):
""" Reads customer provided config on EULA acceptance from disk and returns a boolean.
NOTE: This is a temporary solution and will be deprecated no later than TBD date"""
if not os.path.exists(Constants.Paths.EULA_SETTINGS):
print("NOT accepting EULA for any patch as no corresponding EULA Settings found on the VM")
return False

try:
eula_settings = json.loads(self.read_with_retry(Constants.Paths.EULA_SETTINGS) or 'null')
if eula_settings is not None \
and Constants.EulaSettings.ACCEPT_EULA_FOR_ALL_PATCHES in eula_settings \
and eula_settings[Constants.EulaSettings.ACCEPT_EULA_FOR_ALL_PATCHES] is True:
print("Accept EULA set to True in customer config")
return True
else:
print("Accept EULA not found to be set to True in customer config")
return False
except Exception as error:
print("Error occurred while reading and parsing EULA settings. Not accepting EULA for any patch. Error=[{0}]".format(repr(error)))
return False

@staticmethod
def open(file_path, mode):
""" Provides a file handle to the file_path requested using implicit redirection where required """
for i in range(0, Constants.MAX_FILE_OPERATION_RETRY_COUNT):
try:
return open(file_path, mode)
except Exception as error:
if i < Constants.MAX_FILE_OPERATION_RETRY_COUNT - 1:
time.sleep(i + 1)
else:
raise Exception("Unable to open {0} (retries exhausted). Error: {1}.".format(str(file_path), repr(error)))

def __obtain_file_handle(self, file_path_or_handle, mode='a+'):
""" Pass-through for handle. For path, resolution and handle open with retry. """
is_path = False
if isinstance(file_path_or_handle, str) or not (hasattr(file_path_or_handle, 'read') and hasattr(file_path_or_handle, 'write')):
is_path = True
file_path_or_handle = self.open(file_path_or_handle, mode)
file_handle = file_path_or_handle
return file_handle, is_path

def read_with_retry(self, file_path_or_handle):
""" Reads all content from a given file path in a single operation """
if isinstance(file_path_or_handle, str):
file_handle, was_path = self.__obtain_file_handle(file_path_or_handle, 'r')
value = file_handle.read()
if was_path: # what was passed in was not a file handle, so close the handle that was init here
file_handle.close()
return value
return None
# endregion
5 changes: 4 additions & 1 deletion src/core/src/core_logic/ExecutionConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@


class ExecutionConfig(object):
def __init__(self, env_layer, composite_logger, execution_parameters):
def __init__(self, env_layer, composite_logger, execution_parameters, accept_package_eula):
self.env_layer = env_layer
self.composite_logger = composite_logger
self.execution_parameters = eval(execution_parameters)
Expand Down Expand Up @@ -86,6 +86,9 @@ def __init__(self, env_layer, composite_logger, execution_parameters):
else:
self.composite_logger.log_debug("Not executing in auto-assessment mode.")

# EULA config
self.accept_package_eula = accept_package_eula

def __transform_execution_config_for_auto_assessment(self):
self.activity_id = str(uuid.uuid4())
self.included_classifications_list = self.included_package_name_mask_list = self.excluded_package_name_mask_list = []
Expand Down
35 changes: 7 additions & 28 deletions src/core/src/package_managers/AptitudePackageManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ
super(AptitudePackageManager, self).__init__(env_layer, execution_config, composite_logger, telemetry_writer, status_handler)

security_list_guid = str(uuid.uuid4())

# Accept EULA (End User License Agreement) as per the EULA settings set by user
optional_accept_eula_in_cmd = "ACCEPT_EULA=Y" if execution_config.accept_package_eula else ""

# Repo refresh
self.repo_refresh = 'sudo apt-get -q update'

Expand All @@ -44,15 +48,12 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ
self.single_package_check_versions = 'apt-cache madison <PACKAGE-NAME>'
self.single_package_find_installed_dpkg = 'sudo dpkg -s <PACKAGE-NAME>'
self.single_package_find_installed_apt = 'sudo apt list --installed <PACKAGE-NAME>'
self.single_package_upgrade_simulation_cmd = '''DEBIAN_FRONTEND=noninteractive apt-get -y --only-upgrade true -s install '''
self.single_package_dependency_resolution_template = 'DEBIAN_FRONTEND=noninteractive LANG=en_US.UTF8 apt-get -y --only-upgrade true -s install <PACKAGE-NAME> '
self.single_package_upgrade_simulation_cmd = '''DEBIAN_FRONTEND=noninteractive ''' + optional_accept_eula_in_cmd + ''' apt-get -y --only-upgrade true -s install '''
self.single_package_dependency_resolution_template = 'DEBIAN_FRONTEND=noninteractive ' + optional_accept_eula_in_cmd + ' LANG=en_US.UTF8 apt-get -y --only-upgrade true -s install <PACKAGE-NAME> '

# Install update
# --only-upgrade: upgrade only single package (only if it is installed)
self.single_package_upgrade_cmd = '''sudo DEBIAN_FRONTEND=noninteractive apt-get -y --only-upgrade true install '''

# Accept EULA (End User License Agreement) as per the EULA settings set by user
self.accept_eula_for_patches()
self.single_package_upgrade_cmd = '''sudo DEBIAN_FRONTEND=noninteractive ''' + optional_accept_eula_in_cmd + ''' apt-get -y --only-upgrade true install '''

# Package manager exit code(s)
self.apt_exitcode_ok = 0
Expand Down Expand Up @@ -292,28 +293,6 @@ def get_composite_package_identifier(self, package, package_version):
def install_updates_fail_safe(self, excluded_packages):
return

def accept_eula_for_patches(self):
""" Accepts eula for patches based on the config provided by customers """
if not os.path.exists(Constants.Paths.EULA_SETTINGS):
self.composite_logger.log_warning("NOT accepting EULA for any patch as no corresponding EULA Settings found on the VM")
return

try:
eula_settings = json.loads(self.env_layer.file_system.read_with_retry(Constants.Paths.EULA_SETTINGS, raise_if_not_found=False) or 'null')

if eula_settings is not None \
and Constants.EulaSettings.ACCEPT_EULA_FOR_ALL_PATCHES in eula_settings \
and eula_settings[Constants.EulaSettings.ACCEPT_EULA_FOR_ALL_PATCHES] is True:
self.composite_logger.log_debug("Accepting EULA for all patches as per the EULA setting found on VM")
self.single_package_upgrade_simulation_cmd += " ACCEPT_EULA=Y"
self.single_package_dependency_resolution_template += " ACCEPT_EULA=Y"
self.single_package_upgrade_cmd += " ACCEPT_EULA=Y"
else:
self.composite_logger.log_warning("NOT accepting EULA for any patch as no corresponding acceptance for EULA found on the VM")
return
except Exception as error:
self.composite_logger.log_warning("Error occurred while reading and parsing EULA settings. Not accepting EULA for any patch. Error=[{0}]".format(repr(error)))

# endregion

# region Package Information
Expand Down
4 changes: 0 additions & 4 deletions src/core/src/package_managers/PackageManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,10 +329,6 @@ def install_update_and_dependencies_and_get_status(self, package_and_dependencie
install_result = self.get_installation_status(code, out, exec_cmd, package_and_dependencies[0], package_and_dependency_versions[0], simulate)
return install_result

def accept_eula_for_patches(self):
""" Accepts eula for patches based on the config provided by customers """
pass

# endregion

# region Package Information
Expand Down
4 changes: 0 additions & 4 deletions src/core/src/package_managers/YumPackageManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,6 @@ def install_updates_fail_safe(self, excluded_packages):

self.composite_logger.log_debug("[FAIL SAFE MODE] UPDATING PACKAGES USING COMMAND: " + cmd)
self.invoke_package_manager(cmd)

def accept_eula_for_patches(self):
""" Accepts eula for patches based on the config provided by customers """
pass
# endregion

# region Package Information
Expand Down
4 changes: 0 additions & 4 deletions src/core/src/package_managers/ZypperPackageManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,10 +415,6 @@ def get_composite_package_identifier(self, package, package_version):

def install_updates_fail_safe(self, excluded_packages):
return

def accept_eula_for_patches(self):
""" Accepts eula for patches based on the config provided by customers """
pass
# endregion

# region Package Information
Expand Down
26 changes: 17 additions & 9 deletions src/core/tests/Test_AptitudePackageManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@

class TestAptitudePackageManager(unittest.TestCase):
def setUp(self):
self.runtime = RuntimeCompositor(ArgumentComposer().get_composed_arguments(), True, Constants.APT)
self.argument_composer = ArgumentComposer().get_composed_arguments()
self.runtime = RuntimeCompositor(self.argument_composer, True, Constants.APT)
self.container = self.runtime.container

def tearDown(self):
Expand Down Expand Up @@ -575,10 +576,13 @@ def test_eula_acceptance_for_patches(self):
"LastModified": "2023-08-29"
}
self.runtime.env_layer.file_system.write_with_retry(Constants.Paths.EULA_SETTINGS, '{0}'.format(json.dumps(eula_settings)), mode='w+')
package_manager.accept_eula_for_patches()
self.assertTrue("ACCEPT_EULA=Y" in package_manager.single_package_upgrade_simulation_cmd)
self.assertTrue("ACCEPT_EULA=Y" in package_manager.single_package_dependency_resolution_template)
self.assertTrue("ACCEPT_EULA=Y" in package_manager.single_package_upgrade_cmd)
self.runtime_for_test = RuntimeCompositor(self.argument_composer, True, Constants.APT)
self.container_for_test = self.runtime_for_test.container
package_manager_for_test = self.container_for_test.get('package_manager')

self.assertTrue("ACCEPT_EULA=Y" in package_manager_for_test.single_package_upgrade_simulation_cmd)
self.assertTrue("ACCEPT_EULA=Y" in package_manager_for_test.single_package_dependency_resolution_template)
self.assertTrue("ACCEPT_EULA=Y" in package_manager_for_test.single_package_upgrade_cmd)

def test_eula_not_accepted_for_patches(self):
package_manager = self.container.get('package_manager')
Expand All @@ -594,7 +598,8 @@ def test_eula_not_accepted_for_patches(self):
"LastModified": "2023-08-29"
}
self.runtime.env_layer.file_system.write_with_retry(Constants.Paths.EULA_SETTINGS, '{0}'.format(json.dumps(eula_settings)), mode='w+')
package_manager.accept_eula_for_patches()
self.runtime_for_test = RuntimeCompositor(ArgumentComposer().get_composed_arguments(), True, Constants.APT)
self.container_for_test = self.runtime_for_test.container
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_upgrade_simulation_cmd)
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_dependency_resolution_template)
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_upgrade_cmd)
Expand All @@ -606,7 +611,8 @@ def test_eula_not_accepted_for_patches(self):
"LastModified": "2023-08-29"
}
self.runtime.env_layer.file_system.write_with_retry(Constants.Paths.EULA_SETTINGS, '{0}'.format(json.dumps(eula_settings)), mode='w+')
package_manager.accept_eula_for_patches()
self.runtime_for_test = RuntimeCompositor(ArgumentComposer().get_composed_arguments(), True, Constants.APT)
self.container_for_test = self.runtime_for_test.container
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_upgrade_simulation_cmd)
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_dependency_resolution_template)
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_upgrade_cmd)
Expand All @@ -621,15 +627,17 @@ def test_empty_eula_settings(self):
# Empty eula settings file
eula_settings = ''
self.runtime.env_layer.file_system.write_with_retry(Constants.Paths.EULA_SETTINGS, '{0}'.format(json.dumps(eula_settings)), mode='w+')
package_manager.accept_eula_for_patches()
self.runtime_for_test = RuntimeCompositor(ArgumentComposer().get_composed_arguments(), True, Constants.APT)
self.container_for_test = self.runtime_for_test.container
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_upgrade_simulation_cmd)
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_dependency_resolution_template)
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_upgrade_cmd)

# Empty eula settings file
eula_settings = None
self.runtime.env_layer.file_system.write_with_retry(Constants.Paths.EULA_SETTINGS, '{0}'.format(json.dumps(eula_settings)), mode='w+')
package_manager.accept_eula_for_patches()
self.runtime_for_test = RuntimeCompositor(ArgumentComposer().get_composed_arguments(), True, Constants.APT)
self.container_for_test = self.runtime_for_test.container
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_upgrade_simulation_cmd)
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_dependency_resolution_template)
self.assertTrue("ACCEPT_EULA=Y" not in package_manager.single_package_upgrade_cmd)
Expand Down

0 comments on commit a271126

Please sign in to comment.