From fe285f82cd66c7cb117cdb6268ca01f9896db0a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20Sch=C3=A4fer?= Date: Mon, 23 Sep 2024 10:44:43 +0200 Subject: [PATCH] Add success indicator flag file Added /var/log/distro_migration.exitcode to be written by the migrate service. The file contains the exit code from the zypper process and is used in the migrate tool to know about the overall state of the migration process. The migrate tool initializes the flag file with a failed value. --- suse_migration_services/defaults.py | 4 + suse_migration_services/units/migrate.py | 7 ++ test/unit/units/migrate_test.py | 112 +++++++++++++++++------ 3 files changed, 94 insertions(+), 29 deletions(-) diff --git a/suse_migration_services/defaults.py b/suse_migration_services/defaults.py index a41c0125..e6d208ba 100644 --- a/suse_migration_services/defaults.py +++ b/suse_migration_services/defaults.py @@ -37,6 +37,10 @@ def get_migration_config_file(): def get_migration_log_name(): return 'suse-migration' + @staticmethod + def get_migration_exit_code_file(): + return '/var/log/distro_migration.exitcode' + @staticmethod def get_migration_log_file(system_root=True): migration_log_file = 'var/log/distro_migration.log' diff --git a/suse_migration_services/units/migrate.py b/suse_migration_services/units/migrate.py index ab020b79..1efa097d 100644 --- a/suse_migration_services/units/migrate.py +++ b/suse_migration_services/units/migrate.py @@ -43,6 +43,7 @@ def main(): Logger.setup() log = logging.getLogger(Defaults.get_migration_log_name()) root_path = Defaults.get_system_root_path() + exit_code_file = Defaults.get_migration_exit_code_file() try: log.info('Running migrate service') @@ -99,6 +100,9 @@ def main(): bash_command, zypper_call.output, zypper_call.error ) ) + # report success(0) return code + with open(exit_code_file, 'w') as exit_code: + exit_code.write('0{}'.format(os.linesep)) except Exception as issue: etc_issue_path = os.sep.join( [root_path, 'etc/issue'] @@ -112,6 +116,9 @@ def main(): log_path_migrated_system ) ) + # report failed(1) return code + with open(exit_code_file, 'w') as exit_code: + exit_code.write('1{}'.format(os.linesep)) log.error('migrate service failed with {0}'.format(issue)) raise DistMigrationZypperException( 'Migration failed with {0}'.format(issue) diff --git a/test/unit/units/migrate_test.py b/test/unit/units/migrate_test.py index d077df0b..146e389b 100644 --- a/test/unit/units/migrate_test.py +++ b/test/unit/units/migrate_test.py @@ -1,6 +1,6 @@ import io from unittest.mock import ( - patch, Mock, MagicMock + patch, Mock, MagicMock, call ) from pytest import raises @@ -12,11 +12,27 @@ ) -@patch('suse_migration_services.logger.Logger.setup') -@patch('suse_migration_services.command.Command.run') -@patch('suse_migration_services.units.migrate.log_env') -@patch('suse_migration_services.units.migrate.update_env') class TestMigration(object): + @patch.object(Defaults, 'get_migration_config_file') + def setup(self, mock_get_migration_config_file): + mock_get_migration_config_file.return_value = \ + '../data/migration-config.yml' + self.migration_config = MigrationConfig() + mock_get_migration_config_file.return_value = \ + '../data/migration-config-verbose.yml' + self.migration_config_verbose = MigrationConfig() + mock_get_migration_config_file.return_value = \ + '../data/migration-config-zypper-dup.yml' + self.migration_config_dup = MigrationConfig() + + @patch.object(Defaults, 'get_migration_config_file') + def setup_method(self, cls, mock_get_migration_config_file): + self.setup() + + @patch('suse_migration_services.logger.Logger.setup') + @patch('suse_migration_services.command.Command.run') + @patch('suse_migration_services.units.migrate.log_env') + @patch('suse_migration_services.units.migrate.update_env') @patch('suse_migration_services.defaults.Defaults.get_system_root_path') @patch('suse_migration_services.units.migrate.MigrationConfig') def test_main_zypper_migration_plugin_raises( @@ -35,15 +51,24 @@ def test_main_zypper_migration_plugin_raises( file_handle = mock_open.return_value.__enter__.return_value with raises(DistMigrationZypperException): main() - mock_open.assert_called_once_with( - '../data/etc/issue', 'w' - ) - file_handle.write.assert_called_once_with( - 'Migration has failed, for further details see {0}'.format( - '/var/log/distro_migration.log' - ) - ) + assert mock_open.call_args_list == [ + call('../data/etc/issue', 'w'), + call('/var/log/distro_migration.exitcode', 'w') + ] + assert file_handle.write.call_args_list == [ + call( + 'Migration has failed, for further details see {0}'.format( + '/var/log/distro_migration.log' + ) + ), + call('1\n') + ] + + @patch('suse_migration_services.logger.Logger.setup') + @patch('suse_migration_services.command.Command.run') + @patch('suse_migration_services.units.migrate.log_env') + @patch('suse_migration_services.units.migrate.update_env') @patch('suse_migration_services.defaults.Defaults.get_system_root_path') @patch('suse_migration_services.units.migrate.MigrationConfig') def test_main_zypper_dup_raises( @@ -61,36 +86,57 @@ def test_main_zypper_dup_raises( with patch('builtins.open', create=True): # zypper exit code is 0, all ok main() + + with patch('builtins.open', create=True): # zypper exit code is 1, error zypper_call.returncode = 1 with raises(DistMigrationZypperException): main() + + with patch('builtins.open', create=True): # zypper exit code is 104, error zypper_call.returncode = 104 with raises(DistMigrationZypperException): main() + + with patch('builtins.open', create=True): # zypper exit code is 105, error zypper_call.returncode = 105 with raises(DistMigrationZypperException): main() + + with patch('builtins.open', create=True): # zypper exit code is 106, error zypper_call.returncode = 106 with raises(DistMigrationZypperException): main() + + with patch('builtins.open', create=True): # zypper exit code is 107, all ok zypper_call.returncode = 107 main() + @patch('suse_migration_services.logger.Logger.setup') + @patch('suse_migration_services.command.Command.run') + @patch('suse_migration_services.units.migrate.log_env') + @patch('suse_migration_services.units.migrate.update_env') @patch.object(MigrationConfig, 'get_migration_product') - @patch.object(Defaults, 'get_migration_config_file') + @patch('suse_migration_services.units.migrate.MigrationConfig') def test_main_zypper_migration_plugin( - self, mock_get_migration_config_file, mock_get_system_root_path, + self, mock_MigrationConfig, mock_get_system_root_path, mock_update_env, mock_log_env, mock_Command_run, mock_logger_setup ): + mock_MigrationConfig.return_value = self.migration_config mock_get_system_root_path.return_value = 'SLES/15/x86_64' - mock_get_migration_config_file.return_value = \ - '../data/migration-config.yml' - main() + with patch('builtins.open', create=True) as mock_open: + mock_open.return_value = MagicMock(spec=io.IOBase) + file_handle = mock_open.return_value.__enter__.return_value + main() + + mock_open.assert_called_once_with( + '/var/log/distro_migration.exitcode', 'w' + ) + file_handle.write.assert_called_once_with('0\n') mock_Command_run.assert_called_once_with( [ 'bash', '-c', @@ -109,16 +155,20 @@ def test_main_zypper_migration_plugin( ] ) + @patch('suse_migration_services.logger.Logger.setup') + @patch('suse_migration_services.command.Command.run') + @patch('suse_migration_services.units.migrate.log_env') + @patch('suse_migration_services.units.migrate.update_env') @patch.object(MigrationConfig, 'get_migration_product') - @patch.object(Defaults, 'get_migration_config_file') + @patch('suse_migration_services.units.migrate.MigrationConfig') def test_main_zypper_migration_plugin_verbose( - self, mock_get_migration_config_file, mock_get_system_root_path, + self, mock_MigrationConfig, mock_get_system_root_path, mock_update_env, mock_log_env, mock_Command_run, mock_logger_setup ): + mock_MigrationConfig.return_value = self.migration_config_verbose mock_get_system_root_path.return_value = 'SLES/15/x86_64' - mock_get_migration_config_file.return_value = \ - '../data/migration-config-verbose.yml' - main() + with patch('builtins.open', create=True): + main() mock_Command_run.assert_called_once_with( [ 'bash', '-c', @@ -137,17 +187,21 @@ def test_main_zypper_migration_plugin_verbose( ] ) - @patch.object(Defaults, 'get_migration_config_file') + @patch('suse_migration_services.logger.Logger.setup') + @patch('suse_migration_services.command.Command.run') + @patch('suse_migration_services.units.migrate.log_env') + @patch('suse_migration_services.units.migrate.update_env') + @patch('suse_migration_services.units.migrate.MigrationConfig') def test_main_zypper_dup( - self, mock_get_migration_config_file, - mock_update_env, mock_log_env, mock_Command_run, mock_logger_setup + self, mock_MigrationConfig, mock_update_env, + mock_log_env, mock_Command_run, mock_logger_setup ): + mock_MigrationConfig.return_value = self.migration_config_dup zypper_call = Mock() zypper_call.returncode = 0 mock_Command_run.return_value = zypper_call - mock_get_migration_config_file.return_value = \ - '../data/migration-config-zypper-dup.yml' - main() + with patch('builtins.open', create=True): + main() mock_Command_run.assert_called_once_with( [ 'bash', '-c',