def test_seq_no_from_empty_config_folder(self):
     test_dir = tempfile.mkdtemp()
     ext_config_settings_handler = ExtConfigSettingsHandler(
         self.logger, self.json_file_handler, test_dir)
     seq_no = ext_config_settings_handler.get_seq_no(is_enable_request=True)
     self.assertEqual(None, seq_no)
     shutil.rmtree(test_dir)
    def test_read_file_failures(self):
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler,
            os.path.join(os.path.pardir, "tests", "helpers"))
        # Seq_no invalid, none, -1, empty
        seq_no = None
        self.assertRaises(Exception, ext_config_settings_handler.read_file,
                          seq_no)
        seq_no = -1
        self.assertRaises(Exception, ext_config_settings_handler.read_file,
                          seq_no)
        seq_no = ""
        self.assertRaises(Exception, ext_config_settings_handler.read_file,
                          seq_no)

        # FileNotFound
        seq_no = "12345"
        self.assertRaises(Exception, ext_config_settings_handler.read_file,
                          seq_no)

        # empty file
        test_dir = tempfile.mkdtemp()
        file_name = "123.settings"
        self.runtime.create_temp_file(test_dir, file_name, content=None)
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler, test_dir)
        seq_no = "123"
        self.assertRaises(Exception, ext_config_settings_handler.read_file,
                          seq_no)
        shutil.rmtree(test_dir)

        # empty valid file
        test_dir = tempfile.mkdtemp()
        file_name = "1237.settings"
        self.runtime.create_temp_file(test_dir, file_name, content="{}")
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler, test_dir)
        seq_no = "1237"
        self.assertRaises(Exception, ext_config_settings_handler.read_file,
                          seq_no)
        shutil.rmtree(test_dir)

        # file not valid
        test_dir = tempfile.mkdtemp()
        seq_no = "1237"
        file_name = seq_no + ".settings"
        self.runtime.create_temp_file(test_dir,
                                      file_name,
                                      content='{"runtimeSettings": []}')
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler, test_dir)
        self.assertRaises(Exception, ext_config_settings_handler.read_file,
                          seq_no)
        shutil.rmtree(test_dir)
示例#3
0
    def test_start_daemon(self):
        # setting mocks
        get_python_cmd_backup = ProcessHandler.get_python_cmd
        ProcessHandler.get_python_cmd = self.mock_get_python_cmd
        subprocess_popen_backup = subprocess.Popen

        # Initializing config env
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler,
            os.path.join(os.path.pardir, "tests", "helpers"))
        seq_no = "1234"
        config_settings = ext_config_settings_handler.read_file(seq_no)
        handler_env_file_path = os.path.join(os.path.pardir, "tests",
                                             "helpers")
        ext_env_handler = ExtEnvHandler(
            self.json_file_handler,
            handler_env_file_path=handler_env_file_path)

        # process was not launched
        subprocess.Popen = self.mock_subprocess_popen_process_not_launched
        process_handler = ProcessHandler(self.logger, self.env_layer,
                                         self.ext_output_status_handler)
        process = process_handler.start_daemon(seq_no, config_settings,
                                               ext_env_handler)
        self.assertTrue(process is None)

        # process launched with no issues
        subprocess.Popen = self.mock_subprocess_popen_process_launched_with_no_issues
        process_handler = ProcessHandler(self.logger, self.env_layer,
                                         self.ext_output_status_handler)
        process = process_handler.start_daemon(seq_no, config_settings,
                                               ext_env_handler)
        self.assertTrue(process is not None)

        # process launched but is not running soon after
        subprocess.Popen = self.mock_subprocess_popen_process_not_running_after_launch
        process_handler = ProcessHandler(self.logger, self.env_layer,
                                         self.ext_output_status_handler)

        # todo mock auto assess run command the way core has, where individual commands and expected output for each
        # mock run command output for Auto Assess shell file permission change
        run_command_output_backup = process_handler.env_layer.run_command_output
        process_handler.env_layer.run_command_output = self.mock_run_command_to_set_auto_assess_shell_file_permission

        process = process_handler.start_daemon(seq_no, config_settings,
                                               ext_env_handler)
        self.assertTrue(process is None)

        # resetting mocks
        ProcessHandler.get_python_cmd = get_python_cmd_backup
        subprocess.Popen = subprocess_popen_backup
        process_handler.env_layer.run_command_output = run_command_output_backup
 def test_read_file_success(self):
     ext_config_settings_handler = ExtConfigSettingsHandler(
         self.logger, self.json_file_handler,
         os.path.join(os.path.pardir, "tests", "helpers"))
     seq_no = "1234"
     config_values = ext_config_settings_handler.read_file(seq_no)
     self.assertEqual(
         config_values.__getattribute__(
             self.config_public_settings_fields.operation), "Installation")
     self.assertEqual(
         config_values.__getattribute__(
             self.config_public_settings_fields.reboot_setting),
         "IfRequired")
    def test_get_seq_no_found_in_env_variable_for_enable_cmd(self):
        test_dir = tempfile.mkdtemp()
        os_getenv_backup = os.getenv
        os.getenv = self.mock_getenv

        self.runtime.create_temp_file(test_dir, "1234.settings", content=None)
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler, test_dir)
        seq_no = ext_config_settings_handler.get_seq_no(is_enable_request=True)
        self.assertTrue(seq_no is not None)
        self.assertEqual(seq_no, 1234)

        os.getenv = os_getenv_backup
        shutil.rmtree(test_dir)
 def setUp(self):
     VirtualTerminal().print_lowlight(
         "\n----------------- setup test runner -----------------")
     self.runtime = RuntimeComposer()
     runtime_context_handler = RuntimeContextHandler(self.runtime.logger)
     ext_env_handler = ExtEnvHandler(self.runtime.json_file_handler,
                                     handler_env_file_path=os.path.join(
                                         os.path.pardir, "tests",
                                         "helpers"))
     ext_config_settings_handler = ExtConfigSettingsHandler(
         self.runtime.logger, self.runtime.json_file_handler,
         ext_env_handler.config_folder)
     core_state_handler = CoreStateHandler(ext_env_handler.config_folder,
                                           self.runtime.json_file_handler)
     ext_state_handler = ExtStateHandler(ext_env_handler.config_folder,
                                         self.runtime.utility,
                                         self.runtime.json_file_handler)
     ext_output_status_handler = ExtOutputStatusHandler(
         self.runtime.logger, self.runtime.utility,
         self.runtime.json_file_handler, ext_env_handler.status_folder)
     process_handler = ProcessHandler(self.runtime.logger,
                                      ext_output_status_handler)
     self.action_handler = ActionHandler(
         self.runtime.logger, self.runtime.utility, runtime_context_handler,
         self.runtime.json_file_handler, ext_env_handler,
         ext_config_settings_handler, core_state_handler, ext_state_handler,
         ext_output_status_handler, process_handler,
         "2020-09-02T13:40:54.8862542Z")
示例#7
0
    def test_start_daemon(self):
        # setting mocks
        get_python_cmd_backup = ProcessHandler.get_python_cmd
        ProcessHandler.get_python_cmd = self.mock_get_python_cmd
        subprocess_popen_backup = subprocess.Popen

        # Initializing config env
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler,
            os.path.join(os.path.pardir, "tests", "helpers"))
        seq_no = "1234"
        config_settings = ext_config_settings_handler.read_file(seq_no)
        handler_env_file_path = os.path.join(os.path.pardir, "tests",
                                             "helpers")
        ext_env_handler = ExtEnvHandler(
            self.json_file_handler,
            handler_env_file_path=handler_env_file_path)

        # process was not launched
        subprocess.Popen = self.mock_subprocess_popen_process_not_launched
        process_handler = ProcessHandler(self.logger,
                                         self.ext_output_status_handler)
        process = process_handler.start_daemon(seq_no, config_settings,
                                               ext_env_handler)
        self.assertTrue(process is None)

        # process launched with no issues
        subprocess.Popen = self.mock_subprocess_popen_process_launched_with_no_issues
        process_handler = ProcessHandler(self.logger,
                                         self.ext_output_status_handler)
        process = process_handler.start_daemon(seq_no, config_settings,
                                               ext_env_handler)
        self.assertTrue(process is not None)

        # process launched but is not running soon after
        subprocess.Popen = self.mock_subprocess_popen_process_not_running_after_launch
        process_handler = ProcessHandler(self.logger,
                                         self.ext_output_status_handler)
        process = process_handler.start_daemon(seq_no, config_settings,
                                               ext_env_handler)
        self.assertTrue(process is None)

        # resetting mocks
        ProcessHandler.get_python_cmd = get_python_cmd_backup
        subprocess.Popen = subprocess_popen_backup
示例#8
0
 def test_get_public_config_settings(self):
     ext_config_settings_handler = ExtConfigSettingsHandler(
         self.logger, self.json_file_handler,
         os.path.join(os.path.pardir, "tests", "helpers"))
     seq_no = "1234"
     config_settings = ext_config_settings_handler.read_file(seq_no)
     process_handler = ProcessHandler(self.logger,
                                      self.ext_output_status_handler)
     public_config_settings = process_handler.get_public_config_settings(
         config_settings)
     self.assertTrue(public_config_settings is not None)
     self.assertEqual(
         public_config_settings.get(
             Constants.ConfigPublicSettingsFields.operation),
         "Installation")
     self.assertEqual(
         public_config_settings.get(
             Constants.ConfigPublicSettingsFields.maintenance_run_id),
         "2019-07-20T12:12:14Z")
示例#9
0
def main(argv):
    stdout_file_mirror = None
    file_logger = None
    env_layer = EnvLayer()
    logger = Logger()
    telemetry_writer = TelemetryWriter(logger, env_layer)
    logger.telemetry_writer = telemetry_writer  # Need to set telemetry_writer within logger to enable sending all logs to telemetry
    try:
        # initializing action handler
        # args will have values install, uninstall, etc, as given in MsftLinuxPatchExtShim.sh in the operation var
        cmd_exec_start_time = datetime.datetime.utcnow()
        utility = Utility(logger)
        runtime_context_handler = RuntimeContextHandler(logger)
        json_file_handler = JsonFileHandler(logger)
        ext_env_handler = ExtEnvHandler(json_file_handler)
        env_health_manager = EnvHealthManager(env_layer)
        if ext_env_handler.handler_environment_json is not None and ext_env_handler.config_folder is not None:
            config_folder = ext_env_handler.config_folder
            if config_folder is None or not os.path.exists(config_folder):
                logger.log_error("Config folder not found at [{0}].".format(
                    repr(config_folder)))
                exit(Constants.ExitCode.MissingConfig)

            ext_config_settings_handler = ExtConfigSettingsHandler(
                logger, json_file_handler, config_folder)
            core_state_handler = CoreStateHandler(config_folder,
                                                  json_file_handler)
            ext_state_handler = ExtStateHandler(config_folder, utility,
                                                json_file_handler)
            ext_output_status_handler = ExtOutputStatusHandler(
                logger, utility, json_file_handler,
                ext_env_handler.status_folder)
            process_handler = ProcessHandler(logger, env_layer,
                                             ext_output_status_handler)
            action_handler = ActionHandler(
                logger, env_layer, telemetry_writer, utility,
                runtime_context_handler, json_file_handler, env_health_manager,
                ext_env_handler, ext_config_settings_handler,
                core_state_handler, ext_state_handler,
                ext_output_status_handler, process_handler,
                cmd_exec_start_time)
            action_handler.determine_operation(argv[1])
        else:
            error_cause = "No configuration provided in HandlerEnvironment" if ext_env_handler.handler_environment_json is None else "Path to config folder not specified in HandlerEnvironment"
            error_msg = "Error processing file. [File={0}] [Error={1}]".format(
                Constants.HANDLER_ENVIRONMENT_FILE, error_cause)
            raise Exception(error_msg)
    except Exception as error:
        logger.log_error(repr(error))
        return Constants.ExitCode.HandlerFailed
    finally:
        if stdout_file_mirror is not None:
            stdout_file_mirror.stop()
        if file_logger is not None:
            file_logger.close()
    def setUp(self):
        VirtualTerminal().print_lowlight(
            "\n----------------- setup test runner -----------------")
        self.temp_dir = tempfile.mkdtemp()

        self.runtime = RuntimeComposer()
        runtime_context_handler = RuntimeContextHandler(self.runtime.logger)
        self.ext_env_handler = ExtEnvHandler(
            self.runtime.json_file_handler,
            handler_env_file_path=os.path.join(os.path.pardir, "tests",
                                               "helpers"))
        self.setup_files_and_folders(self.temp_dir)

        self.ext_config_settings_handler = ExtConfigSettingsHandler(
            self.runtime.logger, self.runtime.json_file_handler,
            self.ext_env_handler.config_folder)
        core_state_handler = CoreStateHandler(
            self.ext_env_handler.config_folder, self.runtime.json_file_handler)
        ext_state_handler = ExtStateHandler(self.ext_env_handler.config_folder,
                                            self.runtime.utility,
                                            self.runtime.json_file_handler)
        ext_output_status_handler = ExtOutputStatusHandler(
            self.runtime.logger, self.runtime.utility,
            self.runtime.json_file_handler, self.ext_env_handler.status_folder)
        process_handler = ProcessHandler(self.runtime.logger,
                                         self.runtime.env_layer,
                                         ext_output_status_handler)
        self.action_handler = ActionHandler(
            self.runtime.logger, self.runtime.env_layer,
            self.runtime.telemetry_writer, self.runtime.utility,
            runtime_context_handler, self.runtime.json_file_handler,
            self.runtime.env_health_manager, self.ext_env_handler,
            self.ext_config_settings_handler, core_state_handler,
            ext_state_handler, ext_output_status_handler, process_handler,
            datetime.datetime.utcnow())

        self.backup_get_seq_no_from_env_var = self.ext_config_settings_handler.get_seq_no_from_env_var
        self.ext_config_settings_handler.get_seq_no_from_env_var = self.mock_get_seq_no_from_env_var

        self.backup_mock_os_path_realpath = os.path.realpath
        os.path.realpath = self.mock_os_path_realpath
    def test_get_seq_no_not_found_in_env_variable_for_non_enable_cmd(self):
        # not set in env var
        test_dir = tempfile.mkdtemp()
        self.runtime.create_temp_file(test_dir, "1234.settings", content=None)
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler, test_dir)
        seq_no = ext_config_settings_handler.get_seq_no(
            is_enable_request=False)
        self.assertTrue(seq_no is None)
        shutil.rmtree(test_dir)

        # set in env var, settings file does not exist
        test_dir = tempfile.mkdtemp()
        os_getenv_backup = os.getenv
        os.getenv = self.mock_getenv
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler, test_dir)
        seq_no = ext_config_settings_handler.get_seq_no(
            is_enable_request=False)
        self.assertTrue(seq_no is None)
        os.getenv = os_getenv_backup
        shutil.rmtree(test_dir)
    def test_read_all_config_settings_from_file(self):
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler,
            os.path.join(os.path.pardir, "tests", "helpers"))
        seq_no = ext_config_settings_handler.get_seq_no(is_enable_request=True)
        config_settings = ext_config_settings_handler.read_file(seq_no)

        # verify operation is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.operation), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.operation), "Installation")

        # verify activityId is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.activity_id), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.activity_id),
            "12345-2312-1234-23245-32112")

        # verify startTime is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.start_time), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.start_time),
            "2021-08-08T12:34:56Z")

        # verify maximumDuration is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maximum_duration), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maximum_duration), "PT2H")

        # verify rebootSetting is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.reboot_setting), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.reboot_setting),
            "IfRequired")

        # verify classificationsToInclude is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.include_classifications),
            None)
        self.assertTrue(
            "Critical" in config_settings.__getattribute__(
                self.config_public_settings_fields.include_classifications)
            and "Security" in config_settings.__getattribute__(
                self.config_public_settings_fields.include_classifications))

        # verify patchesToInclude is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.include_patches), None)
        self.assertTrue(
            "*ern*=1.2*" in config_settings.__getattribute__(
                self.config_public_settings_fields.include_patches)
            and "kern*=1.23.45" in config_settings.__getattribute__(
                self.config_public_settings_fields.include_patches))

        # verify patchesToExclude is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.exclude_patches), None)
        self.assertTrue("test" in config_settings.__getattribute__(
            self.config_public_settings_fields.exclude_patches))

        # verify internalSettings is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.internal_settings), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.internal_settings), "test")

        # verify patchMode is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.patch_mode), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.patch_mode),
            "AutomaticByPlatform")

        # verify maintenanceRunId is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maintenance_run_id), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maintenance_run_id),
            "2019-07-20T12:12:14Z")

        # verify healthStoreId is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.health_store_id), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.health_store_id),
            "2021-09-15T12:12:14Z")

        # verify assessmentMode is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.assessment_mode), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.assessment_mode),
            "AutomaticByPlatform")

        # verify maximumAssessmentInterval is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maximum_assessment_interval
            ), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maximum_assessment_interval
            ), "PT3H")
    def test_are_config_settings_valid(self):
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler, "mockConfig")

        runtime_settings_key = Constants.RUNTIME_SETTINGS
        handler_settings_key = Constants.HANDLER_SETTINGS
        public_settings_key = Constants.PUBLIC_SETTINGS

        config_settings_json = None
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))

        config_settings_json = []
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))

        config_settings_json = {}
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))

        # runtimeSettings not in file
        config_settings_json = {'key': 'test'}
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        # runtimeSettings not of type list
        config_settings_json = {runtime_settings_key: "test"}
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        config_settings_json = {runtime_settings_key: {}}
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        # runtimeSettings is None or empty
        config_settings_json = {runtime_settings_key: None}
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        # runtimeSettings is on len 0
        config_settings_json = {runtime_settings_key: []}
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))

        # handlerSettings not in runtimeSettings
        config_settings_json = {runtime_settings_key: ["test"]}
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        # handlerSettings not of type dict
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: []
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: "test"
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: ["test"]
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        # handlerSettings is None or empty
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: None
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {}
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))

        # publicSettings not in handlerSettings
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {
                    "testKey": "testVal"
                }
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        # handlerSettings not of type dict
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {
                    "testKey": "testVal",
                    public_settings_key: []
                }
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {
                    "testKey": "testVal",
                    public_settings_key: "test"
                }
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {
                    "testKey": "testVal",
                    public_settings_key: ["test"]
                }
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        # publicSettings is None or empty
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {
                    "testKey": "testVal",
                    public_settings_key: None
                }
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {
                    "testKey": "testVal",
                    public_settings_key: {}
                }
            }]
        }
        self.assertFalse(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))

        # accepted config settings
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {
                    "testKey": "testVal",
                    public_settings_key: {
                        self.config_public_settings_fields.operation:
                        "test",
                        self.config_public_settings_fields.activity_id:
                        "12345-2312-1234-23245-32112",
                        self.config_public_settings_fields.start_time:
                        "2019-07-20T12:12:14Z",
                        self.config_public_settings_fields.maximum_duration:
                        "20m",
                        self.config_public_settings_fields.reboot_setting:
                        "IfRequired",
                        self.config_public_settings_fields.include_classifications:
                        ["Critical", "Security"],
                        self.config_public_settings_fields.include_patches:
                        ["*", "test*", "*ern*=1.2*", "kern*=1.23.45"],
                        self.config_public_settings_fields.exclude_patches:
                        ["*", "test", "*test"],
                        self.config_public_settings_fields.internal_settings:
                        "<serialized-json>",
                        self.config_public_settings_fields.maintenance_run_id:
                        "2019-07-20T12:12:14Z",
                        self.config_public_settings_fields.patch_mode:
                        "AutomaticByPlatform",
                        self.config_public_settings_fields.assessment_mode:
                        "AutomaticByPlatform",
                        self.config_public_settings_fields.maximum_assessment_interval:
                        "PT3H",
                    }
                }
            }]
        }
        self.assertTrue(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))

        # Testing with only required fields
        config_settings_json = {
            runtime_settings_key: [{
                handler_settings_key: {
                    public_settings_key: {
                        self.config_public_settings_fields.operation:
                        "test",
                        self.config_public_settings_fields.activity_id:
                        "12345-2312-1234-23245-32112",
                        self.config_public_settings_fields.start_time:
                        "2019-07-20T12:12:14Z"
                    }
                }
            }]
        }
        self.assertTrue(
            ext_config_settings_handler.are_config_settings_valid(
                config_settings_json))
    def test_seq_no_from_config_folder(self):
        files = [{
            "name": '1.json',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": '2.json',
            "lastModified": '2018-07-20T12:12:14Z'
        }, {
            "name": '11.json',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": '12.settings',
            "lastModified": '2019-07-02T12:12:14Z'
        }, {
            "name": '121.settings',
            "lastModified": '2017-07-20T12:12:14Z'
        }, {
            "name": '122.settings',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": '123.json',
            "lastModified": '2019-07-20T11:12:14Z'
        }, {
            "name": '10.settings',
            "lastModified": '2019-07-20T10:12:14Z'
        }, {
            "name": '111.settings',
            "lastModified": '2019-07-20T12:10:14Z'
        }, {
            "name": 'dir1',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": '111111',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": '2.settings',
            "lastModified": '2019-07-20T12:12:12Z'
        }, {
            "name": '3a.settings',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": 'aa.settings',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": 'a3.settings',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": '22.settings.settings',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": '0.settings',
            "lastModified": '2019-07-19T12:12:14Z'
        }, {
            "name": 'abc.123.settings',
            "lastModified": '2019-07-20T12:12:14Z'
        }, {
            "name": '.settings',
            "lastModified": '2019-07-20T12:12:14Z'
        }]

        test_dir = tempfile.mkdtemp()
        for file in files:
            file_path = os.path.join(test_dir, file["name"])
            with open(file_path, 'w') as f:
                timestamp = time.mktime(
                    datetime.strptime(
                        file["lastModified"],
                        Constants.UTC_DATETIME_FORMAT).timetuple())
                os.utime(file_path, (timestamp, timestamp))
                f.close()
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler, test_dir)
        seq_no = ext_config_settings_handler.get_seq_no(is_enable_request=True)
        self.assertEqual(122, seq_no)
        shutil.rmtree(test_dir)
    def test_read_all_config_settings_from_file(self):
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler,
            os.path.join(os.path.pardir, "tests", "helpers"))
        seq_no = ext_config_settings_handler.get_seq_no(is_enable_request=True)
        config_settings = ext_config_settings_handler.read_file(seq_no)

        # verify operation is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.operation), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.operation), "Installation")

        # verify activityId is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.activity_id), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.activity_id),
            "12345-2312-1234-23245-32112")

        # verify startTime is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.start_time), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.start_time),
            "2019-07-20T12:12:14Z")

        # verify maximumDuration is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maximum_duration), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maximum_duration), "PT2H")

        # verify rebootSetting is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.reboot_setting), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.reboot_setting),
            "IfRequired")

        # verify classificationsToInclude is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.include_classifications),
            None)
        self.assertTrue(
            "Critical" in config_settings.__getattribute__(
                self.config_public_settings_fields.include_classifications)
            and "Security" in config_settings.__getattribute__(
                self.config_public_settings_fields.include_classifications))

        # verify patchesToInclude is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.include_patches), None)
        self.assertTrue(
            "*ern*=1.2*" in config_settings.__getattribute__(
                self.config_public_settings_fields.include_patches)
            and "kern*=1.23.45" in config_settings.__getattribute__(
                self.config_public_settings_fields.include_patches))

        # verify patchesToExclude is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.exclude_patches), None)
        self.assertTrue("test" in config_settings.__getattribute__(
            self.config_public_settings_fields.exclude_patches))

        # verify internalSettings is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.internal_settings), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.internal_settings), "test")

        # verify maintenanceRunId is read successfully
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maintenance_run_id), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maintenance_run_id),
            "2019-07-20T12:12:14Z")

        # verify patchRolloutId is read successfully if maintenanceRunId is not available
        # todo: remove this test and patch_rollout_id_bak_compat_test.settings file, once patch rollout id is removed
        ext_config_settings_handler = ExtConfigSettingsHandler(
            self.logger, self.json_file_handler,
            os.path.join(os.path.pardir, "tests", "helpers"))
        config_settings = ext_config_settings_handler.read_file(
            "patch_rollout_id_bak_compat_test")
        self.assertNotEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maintenance_run_id), None)
        self.assertEqual(
            config_settings.__getattribute__(
                self.config_public_settings_fields.maintenance_run_id),
            "2019-07-22T12:12:14Z")