From b277b3880d138e55ac3681ad3563bb1ba484d555 Mon Sep 17 00:00:00 2001 From: Niall Byrne <9848926+niall-byrne@users.noreply.github.com> Date: Wed, 17 Jan 2024 20:58:58 +0000 Subject: [PATCH] feat(INSTALLER): idempotent user config installation --- .../steps/step_install_config_file.py | 5 ++- .../tests/test_step_install_config_file.py | 39 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/pi_portal/installation/steps/step_install_config_file.py b/pi_portal/installation/steps/step_install_config_file.py index a4c03c10..f50c78a8 100644 --- a/pi_portal/installation/steps/step_install_config_file.py +++ b/pi_portal/installation/steps/step_install_config_file.py @@ -29,7 +29,10 @@ def invoke(self) -> None: """Install the user's configuration file.""" self.log.info("Installing the user's configuration file ...") - shutil.copy(self.config_file_path, config.PATH_USER_CONFIG) + try: + shutil.copy(self.config_file_path, config.PATH_USER_CONFIG) + except shutil.SameFileError: + pass self.log.info("Done writing the user's configuration file.") self.log.info("Setting permissions on the user's configuration file ...") diff --git a/pi_portal/installation/steps/tests/test_step_install_config_file.py b/pi_portal/installation/steps/tests/test_step_install_config_file.py index ff02a8c4..14ced6d1 100644 --- a/pi_portal/installation/steps/tests/test_step_install_config_file.py +++ b/pi_portal/installation/steps/tests/test_step_install_config_file.py @@ -1,5 +1,6 @@ """Test the StepInstallConfigFile class.""" import logging +import shutil from io import StringIO from unittest import mock @@ -30,7 +31,7 @@ def test__initialize__inheritance( base_step.StepBase, ) - def test__invoke__success( + def test__invoke__success__no_exception( self, step_install_config_files_instance: StepInstallConfigFile, mocked_config_file: str, @@ -62,7 +63,41 @@ def test__invoke__success( "configuration file.\n" ) - def test__invoke__failure( + def test__invoke__success__same_file_error( + self, + step_install_config_files_instance: StepInstallConfigFile, + mocked_config_file: str, + mocked_copy: mock.Mock, + mocked_file_system: mock.Mock, + mocked_stream: StringIO, + ) -> None: + mocked_copy.side_effect = shutil.SameFileError + + step_install_config_files_instance.invoke() + + mocked_copy.assert_called_once_with( + mocked_config_file, + config.PATH_USER_CONFIG, + ) + assert mocked_file_system.mock_calls == [ + mock.call(config.PATH_USER_CONFIG), + mock.call().ownership( + config.PI_PORTAL_USER, + config.PI_PORTAL_USER, + ), + mock.call().permissions("600"), + ] + assert mocked_stream.getvalue() == \ + ( + "test - INFO - Installing the user's configuration file ...\n" + "test - INFO - Done writing the user's configuration file.\n" + "test - INFO - Setting permissions on the user's " + "configuration file ...\n" + "test - INFO - Done setting permissions on the user's " + "configuration file.\n" + ) + + def test__invoke__failure__os_error( self, step_install_config_files_instance: StepInstallConfigFile, mocked_config_file: str,