def fixture_check_plugin(monkeypatch): return CheckPlugin( CheckPluginName("unit_test_check_plugin"), [ParsedSectionName("norris")], "Unit Test", None, # type: ignore[arg-type] # irrelevant for test None, # type: ignore[arg-type] # irrelevant for test None, # type: ignore[arg-type] # irrelevant for test None, # type: ignore[arg-type] # irrelevant for test None, # type: ignore[arg-type] # irrelevant for test None, # type: ignore[arg-type] # irrelevant for test None, # type: ignore[arg-type] # irrelevant for test None, # type: ignore[arg-type] # irrelevant for test None, # type: ignore[arg-type] # irrelevant for test )
def _validate_service_name(plugin_name: CheckPluginName, service_name: str) -> None: if not isinstance(service_name, str): raise TypeError("service_name must be str, got %r" % (service_name,)) if not service_name: raise ValueError("service_name must not be empty") if service_name.count(ITEM_VARIABLE) not in (0, 1): raise ValueError("service_name must contain %r at most once" % ITEM_VARIABLE) if plugin_name.is_management_name() is not service_name.startswith(MANAGEMENT_DESCR_PREFIX): raise ValueError( "service name and description inconsistency: Please neither have your plugins " "name start with %r, nor the description with %r. In the rare case that you want to " "implement a check plugin explicitly designed for management boards (and nothing else)," " you must do both of the above." % (CheckPluginName.MANAGEMENT_PREFIX, MANAGEMENT_DESCR_PREFIX))
def test_dump_precompiled_hostcheck(monkeypatch, serial): ts = Scenario().add_host("localhost") config_cache = ts.apply(monkeypatch) # Ensure a host check is created monkeypatch.setattr( core_nagios, "_get_needed_plugin_names", lambda c: (set(), {CheckPluginName("uptime")}, set()), ) host_check = core_nagios._dump_precompiled_hostcheck( config_cache, serial, "localhost") assert host_check is not None assert host_check.startswith("#!/usr/bin/env python3")
def test_section_vutlan_ems_smoke(fix_register: FixRegister): check = fix_register.check_plugins[CheckPluginName("vutlan_ems_smoke")] section = { "Analog-5": SmokeSensor(name="Analog-5", state=0), "Banana": SmokeSensor(name="Banana", state=2), } result = check.discovery_function(section=section) expected_section_result = [ Service(item="Analog-5"), Service(item="Banana"), ] assert list(result) == expected_section_result
def test_check_timemachine_state_warn(fix_register: FixRegister, monkeypatch): check = fix_register.check_plugins[CheckPluginName("timemachine")] monkeypatch.setattr(datetime, "datetime", MockedDateTime) monkeypatch.setenv("TZ", "Europe/Berlin") result = list( check.check_function( params={"age": (86400, 172800)}, section="/Volumes/Backup/Backups.backupdb/macvm/2022-05-04-202610", )) assert result == [ Result( state=State.WARN, summary= "Last backup was at 2022-05-04 20:26:10: 1 day 18 hours ago (warn/crit at 1 day 0 hours ago/2 days 0 hours ago)", ) ]
def test_check_future_backup_date(fix_register: FixRegister, monkeypatch): check = fix_register.check_plugins[CheckPluginName("timemachine")] monkeypatch.setattr(datetime, "datetime", MockedDateTime) monkeypatch.setenv("TZ", "Europe/Berlin") result = list( check.check_function( params={"age": (86400, 172800)}, section="/Volumes/Backup/Backups.backupdb/macvm/2022-05-07-202610", )) assert result == [ Result( state=State.UNKNOWN, summary= "Timestamp of last backup is in the future: 2022-05-07 20:26:10", ) ]
def test_create_check_plugin(): plugin = check_plugins.create_check_plugin(**MINIMAL_CREATION_KWARGS) assert plugin.name == CheckPluginName(MINIMAL_CREATION_KWARGS["name"]) assert plugin.sections == [ ParsedSectionName(MINIMAL_CREATION_KWARGS["name"]) ] assert plugin.service_name == MINIMAL_CREATION_KWARGS["service_name"] assert plugin.discovery_function.__name__ == MINIMAL_CREATION_KWARGS[ "discovery_function"].__name__ assert plugin.discovery_default_parameters == {} assert plugin.discovery_ruleset_name is None assert plugin.check_function.__name__ == MINIMAL_CREATION_KWARGS[ "check_function"].__name__ assert plugin.check_default_parameters == {} assert plugin.check_ruleset_name is None
def test_load_host_value_store_loads_file(monkeypatch): service_id = (CheckPluginName("test_service"), None) monkeypatch.setattr( store, "load_text_from_file", lambda *_a, **_kw: "{('%s', %r, 'loaded_file'): True}" % service_id, ) with load_host_value_store( "test_load_host_value_store_loads_file", store_changes=False, ) as mgr: with mgr.namespace(service_id): assert get_value_store()["loaded_file"]
def test_check_oracle_instance( fix_register: FixRegister, agent_line: list[str], expected_result: CheckResult, ) -> None: assert (list(fix_register.check_plugins[CheckPluginName( "oracle_instance")].check_function( item="IC731", params={ "logins": 2, "noforcelogging": 1, "noarchivelog": 1, "primarynotopen": 2, }, section=parse_oracle_instance([agent_line]), )) == expected_result)
def test_check_oracle_performance_dbtime( fix_register: FixRegister, monkeypatch, item: str, params: Mapping[str, Sequence[Tuple[str, Tuple[float, float]]]], parsed, expected_result: Sequence[Tuple[str, Mapping]], ): monkeypatch.setattr(cmk.base.item_state, "raise_counter_wrap", lambda: None) check_plugin = fix_register.check_plugins[CheckPluginName( "oracle_performance_dbtime")] results = list( check_plugin.check_function(item=item, params=params, section=parsed)) assert results == expected_result
def _parse_autocheck_entry( hostname: HostName, entry: Union[Tuple, Dict], service_description: GetServiceDescription, ) -> Optional[Service]: if isinstance(entry, tuple): check_plugin_name, item, parameters = _parse_pre_16_tuple_autocheck_entry( entry) dict_service_labels = {} elif isinstance(entry, dict): check_plugin_name, item, parameters, dict_service_labels = \ _parse_dict_autocheck_entry(entry) else: raise Exception("Invalid autocheck: Wrong type: %r" % entry) if not isinstance(check_plugin_name, str): raise Exception("Invalid autocheck: Wrong check plugin type: %r" % check_plugin_name) if isinstance(item, (int, float)): # NOTE: We exclude complex here. :-) item = str(int(item)) elif not isinstance(item, (str, type(None))): raise Exception("Invalid autocheck: Wrong item type: %r" % item) try: # Pre 1.7 check plugins had dots in the check plugin name. With the new check API in # 1.7 they are replaced by '_', renaming e.g. 'cpu.loads' to 'cpu_loads'. plugin_name = CheckPluginName(maincheckify(check_plugin_name)) except Exception: raise Exception("Invalid autocheck: Wrong check plugin name: %r" % check_plugin_name) try: description = service_description(hostname, plugin_name, item) except Exception: return None # ignore return Service( check_plugin_name=plugin_name, item=item, description=description, parameters=parameters, service_labels=_parse_discovered_service_label_from_dict( dict_service_labels), )
def test_discover_oracle_instance(fix_register: FixRegister) -> None: assert list( fix_register.check_plugins[CheckPluginName("oracle_instance")].discovery_function( { "a": InvalidData(sid="a"), "b": GeneralError( sid="b", err="something went wrong", ), "c": Instance(sid="c"), }, ) ) == [ Service(item="a"), Service(item="b"), Service(item="c"), ]
def test_docker_container_diskstat( fix_register, string_table, expected_result, ) -> None: agent_section = fix_register.agent_sections[SectionName("docker_container_mem")] plugin = fix_register.check_plugins[CheckPluginName("mem_used")] parsed = agent_section.parse_function(string_table) assert ( list( plugin.check_function( params={"levels": (80, 90)}, section=parsed, ) ) == expected_result )
def test_check_levels_predictive_default_render_func(mocker): mocker.patch( "cmk.base.check_api._prediction.get_levels", return_value=(None, (2.2, 4.2, None, None)) ) irrelevant_test_parameters: LegacyCheckParameters = {} service = Service( item=None, check_plugin_name=CheckPluginName("test_check"), description="unittest-service-description", parameters=irrelevant_test_parameters, ) with current_host("unittest"), current_service(service): result = next(utils.check_levels_predictive(42.42, metric_name="metric_name", levels={})) assert isinstance(result, Result) assert result.summary.startswith("42.42")
def test_plugin_name_sort(): plugin_dict = { CheckPluginName("Stuart"): None, CheckPluginName("Bob"): None, CheckPluginName("Dave"): None, } assert sorted(plugin_dict) == [ CheckPluginName("Bob"), CheckPluginName("Dave"), CheckPluginName("Stuart") ]
def service_table() -> discovery.ServicesTable: return { (CheckPluginName("check_plugin_name"), "New Item 1"): ( "new", discovery.Service( CheckPluginName("check_plugin_name"), "New Item 1", "Test Description New Item 1", {}, ), [], ), (CheckPluginName("check_plugin_name"), "New Item 2"): ( "new", discovery.Service( CheckPluginName("check_plugin_name"), "New Item 2", "Test Description New Item 2", {}, ), [], ), (CheckPluginName("check_plugin_name"), "Vanished Item 1"): ( "vanished", discovery.Service( CheckPluginName("check_plugin_name"), "Vanished Item 1", "Test Description Vanished Item 1", {}, ), [], ), (CheckPluginName("check_plugin_name"), "Vanished Item 2"): ( "vanished", discovery.Service( CheckPluginName("check_plugin_name"), "Vanished Item 2", "Test Description Vanished Item 2", {}, ), [], ), }
def test_load_host_value_store_loads_file(monkeypatch): service_id = (CheckPluginName("test_service"), None) monkeypatch.setattr( item_state.store, "load_object_from_file", lambda *_a, **_kw: { (str(service_id[0]), service_id[1], "loaded_file"): True }, ) with item_state.load_host_value_store( "test_load_host_value_store_loads_file", store_changes=False, ) as mgr: with mgr.namespace(service_id): assert item_state.get_value_store()["loaded_file"]
def fixture_results(checkplugin, section, params, mocker: MockerFixture): params = {k: params for k in checkplugin.metrics} mocker.patch( "cmk.base.check_api._prediction.get_levels", return_value=(None, (2.2, 4.2, None, None)) ) with current_host("unittest"), current_service( CheckPluginName("test_check"), "unittest-service-description" ): results = list( checkplugin.function( item=ITEM, params=params, section_gcp_service_cloud_functions=section, section_gcp_assets=None, ) ) return results, checkplugin
def test_check_oracle_instance_empty_section(fix_register: FixRegister) -> None: assert list( fix_register.check_plugins[CheckPluginName("oracle_instance")].check_function( item="item", params={ "logins": 2, "noforcelogging": 1, "noarchivelog": 1, "primarynotopen": 2, }, section={}, ) ) == [ Result( state=State.CRIT, summary="Database or necessary processes not running or login failed", ) ]
def _extract_disabled_snmp_sections_from_ignored_checks( self, all_rulesets): ignored_checks_ruleset = all_rulesets.get("ignored_checks") if ignored_checks_ruleset.is_empty(): # nothing to do return if not all_rulesets.get("snmp_exclude_sections").is_empty(): # this must be an upgrade from 2.0.0 or newer - don't mess with # the existing rules! return self._logger.log(VERBOSE, "Extracting excluded SNMP sections") all_snmp_section_names = set( s.name for s in register.iter_all_snmp_sections()) all_check_plugin_names = set( p.name for p in register.iter_all_check_plugins()) all_inventory_plugin_names = set( i.name for i in register.iter_all_inventory_plugins()) snmp_exclude_sections_ruleset = cmk.gui.watolib.rulesets.Ruleset( "snmp_exclude_sections", ignored_checks_ruleset.tag_to_group_map) for folder, _index, rule in ignored_checks_ruleset.get_rules(): disabled = {CheckPluginName(n) for n in rule.value} still_needed_sections_names = set( register.get_relevant_raw_sections( check_plugin_names=all_check_plugin_names - disabled, inventory_plugin_names=all_inventory_plugin_names, )) sections_to_disable = all_snmp_section_names - still_needed_sections_names new_rule = cmk.gui.watolib.rulesets.Rule( rule.folder, snmp_exclude_sections_ruleset) new_rule.from_config(rule.to_config()) new_rule.id = cmk.gui.watolib.rulesets.utils.gen_id() new_rule.value = { # type: ignore[assignment] 'sections_disabled': sorted(str(s) for s in sections_to_disable), 'sections_enabled': [], } snmp_exclude_sections_ruleset.append_rule(folder, new_rule) all_rulesets.set(snmp_exclude_sections_ruleset.name, snmp_exclude_sections_ruleset)
def _extract_disabled_snmp_sections_from_ignored_checks(self, all_rulesets): ignored_checks_ruleset = all_rulesets.get("ignored_checks") if ignored_checks_ruleset.is_empty(): # nothing to do return if not all_rulesets.get("snmp_exclude_sections").is_empty(): # this must be an upgrade from 2.0.0 or newer - don't mess with # the existing rules! return self._logger.log(VERBOSE, "Extracting excluded SNMP sections") all_snmp_section_names = set(s.name for s in register.iter_all_snmp_sections()) all_check_plugin_names = set(p.name for p in register.iter_all_check_plugins()) all_inventory_plugin_names = set(i.name for i in register.iter_all_inventory_plugins()) snmp_exclude_sections_ruleset = cmk.gui.watolib.rulesets.Ruleset( "snmp_exclude_sections", ignored_checks_ruleset.tag_to_group_map) for folder, _index, rule in ignored_checks_ruleset.get_rules(): disabled = {CheckPluginName(n) for n in rule.value} still_needed_sections_names = set( register.get_relevant_raw_sections( check_plugin_names=all_check_plugin_names - disabled, inventory_plugin_names=all_inventory_plugin_names, )) sections_to_disable = all_snmp_section_names - still_needed_sections_names if not sections_to_disable: continue new_rule = cmk.gui.watolib.rulesets.Rule(rule.folder, snmp_exclude_sections_ruleset) new_rule.from_config(rule.to_config()) new_rule.id = cmk.gui.watolib.rulesets.utils.gen_id() new_rule.value = { # type: ignore[assignment] 'sections_disabled': sorted(str(s) for s in sections_to_disable), 'sections_enabled': [], } new_rule.rule_options["comment"] = ( '%s - Checkmk: automatically converted during upgrade from rule ' '"Disabled checks". Please review if these rules can be deleted.') % time.strftime( "%Y-%m-%d %H:%M", time.localtime()) snmp_exclude_sections_ruleset.append_rule(folder, new_rule) all_rulesets.set(snmp_exclude_sections_ruleset.name, snmp_exclude_sections_ruleset)
def test_create_check_plugin_from_legacy_wo_params(monkeypatch): monkeypatch.setattr(config, '_check_contexts', {"norris": {}}) plugin = check_plugins_legacy.create_check_plugin_from_legacy( "norris", MINIMAL_CHECK_INFO, [], ) assert plugin.name == CheckPluginName("norris") assert plugin.sections == [ParsedSectionName("norris")] assert plugin.service_name == MINIMAL_CHECK_INFO["service_description"] assert plugin.discovery_function.__name__ == 'discovery_migration_wrapper' assert plugin.discovery_default_parameters == {} assert plugin.discovery_ruleset_name is None assert plugin.check_function.__name__ == 'check_migration_wrapper' assert plugin.check_default_parameters == {} assert plugin.check_ruleset_name is None assert plugin.cluster_check_function.__name__ == "cluster_legacy_mode_from_hell"
def test__get_service_filter_func_same_lists(monkeypatch, whitelist, result): monkeypatch.setattr(config, "service_description", lambda h, c, i: "Test Description") service_filters = _filters.ServiceFilters.from_settings({"service_whitelist": whitelist}) service = _filters.Service(CheckPluginName("check_plugin_name"), "item", "Test Description", None) assert service_filters.new is not None assert service_filters.new("hostname", service) is result service_filters_inv = _filters.ServiceFilters.from_settings({"service_blacklist": whitelist}) assert service_filters_inv.new is not None assert service_filters_inv.new("hostname", service) is not result service_filters_both = _filters.ServiceFilters.from_settings({ "service_whitelist": whitelist, "service_blacklist": whitelist, }) assert service_filters_both.new is not None assert service_filters_both.new("hostname", service) is False
def test_check_ps_common_cpu(data): def time_info(service, agent_info, check_time, cputime, cpu_cores): with on_time(datetime.datetime.utcfromtimestamp(check_time), "CET"): _cpu_info, parsed_lines = ps_section.parse_ps(splitter(agent_info.format(cputime))) lines_with_node_name: List[Tuple[Optional[str], ps_utils.ps_info, List[str]]] = [ (None, ps_info, cmd_line) for (ps_info, cmd_line) in parsed_lines] return list(ps_utils.check_ps_common( label="Processes", item=service.item, params=service.parameters, # type: ignore[arg-type] process_lines=lines_with_node_name, cpu_cores=cpu_cores, total_ram=None, )) service = Service( item="test", parameters={ "process": "~test", "user": None, "levels": (1, 1, 99999, 99999) # from factory defaults }) if data.cpu_rescale_max is not None: service.parameters.update({"cpu_rescale_max": data.cpu_rescale_max}) with value_store.context(CheckPluginName("ps"), "unit-test"): # Initialize counters time_info(service, data.agent_info, 0, 0, data.cpu_cores) # Check_cpu_utilization output = time_info(service, data.agent_info, 60, data.cputime, data.cpu_cores) assert output[:6] == [ Result(state=state.OK, summary="Processes: 1"), Metric("count", 1, levels=(100000, 100000), boundaries=(0, None)), Result(state=state.OK, notice="virtual: 105 KiB"), Metric("vsz", 105), Result(state=state.OK, notice="physical: 30.0 KiB"), Metric("rss", 30), ] assert output[8:] == [ Result(state=state.OK, notice="Running for: 3 hours 59 minutes"), ]
def _parse_autocheck_entry( hostname: HostName, entry: Union[Tuple, Dict], service_description: GetServiceDescription, ) -> Optional[Service]: if isinstance(entry, tuple): check_plugin_name, item, parameters = _parse_pre_16_tuple_autocheck_entry( entry) dict_service_labels = {} elif isinstance(entry, dict): check_plugin_name, item, parameters, dict_service_labels = \ _parse_dict_autocheck_entry(entry) else: raise Exception("Invalid autocheck: Wrong type: %r" % entry) if not isinstance(check_plugin_name, str): raise Exception("Invalid autocheck: Wrong check plugin type: %r" % check_plugin_name) if isinstance(item, (int, float)): # NOTE: We exclude complex here. :-) item = str(int(item)) elif not isinstance(item, (str, type(None))): raise Exception("Invalid autocheck: Wrong item type: %r" % item) try: # TODO (mo): centralize maincheckify: CMK-4295 description = service_description( hostname, CheckPluginName(maincheckify(check_plugin_name)), item, ) except Exception: return None # ignore return Service( check_plugin_name=check_plugin_name, item=item, description=description, parameters=parameters, service_labels=_parse_discovered_service_label_from_dict( dict_service_labels), )
def test_check_ps_common(inv_item, reference): parsed: List = [] for info in generate_inputs(): _cpu_cores, data = ps_section.parse_ps(info) parsed.extend((None, ps_info, cmd_line) for (ps_info, cmd_line) in data) total_ram = 1024**3 if "emacs" in inv_item.item else None with on_time(1540375342, "CET"): factory_defaults = {"levels": (1, 1, 99999, 99999)} factory_defaults.update(inv_item.parameters) with value_store.context(CheckPluginName("ps"), "unit-test"): test_result = list(ps_utils.check_ps_common( label="Processes", item=inv_item.item, params=factory_defaults, # type: ignore[arg-type] process_lines=parsed, cpu_cores=1, total_ram=total_ram, )) assert test_result == reference
def test_get_cmk_passive_service_attributes(monkeypatch, hostname, result): ts = Scenario().add_host("localhost") ts.add_host("blub") ts.set_option( "extra_service_conf", { "contact_groups": [(u'ding', ['localhost'], ["CPU load$"]),], "check_interval": [ (40.0, ['blub'], ["Check_MK$"]), (33.0, ['localhost'], ["CPU load$"]), ], }) config_cache = ts.apply(monkeypatch) host_config = config_cache.get_host_config(hostname) check_mk_attrs = core_config.get_service_attributes(hostname, "Check_MK", config_cache) service = Service(CheckPluginName("cpu_loads"), None, "CPU load", {}) service_spec = core_config.get_cmk_passive_service_attributes(config_cache, host_config, service, check_mk_attrs) assert service_spec == result
def test_compile_delayed_host_check(monkeypatch, serial): hostname = "localhost" ts = Scenario().add_host(hostname) ts.set_option("delay_precompile", True) config_cache = ts.apply(monkeypatch) # Ensure a host check is created monkeypatch.setattr( core_nagios, "_get_needed_plugin_names", lambda c: (set(), {CheckPluginName("uptime")}, set()), ) source_file = core_nagios.HostCheckStore.host_check_source_file_path( serial, hostname) compiled_file = core_nagios.HostCheckStore.host_check_file_path( serial, hostname) assert config.delay_precompile is True assert not source_file.exists() assert not compiled_file.exists() # Write the host check source file host_check = core_nagios._dump_precompiled_hostcheck( config_cache, serial, hostname, verify_site_python=False) assert host_check is not None core_nagios.HostCheckStore().write(serial, hostname, host_check) # The compiled file path links to the source file until it has been executed for the first # time. Then the symlink is replaced with the compiled file assert source_file.exists() assert compiled_file.exists() assert compiled_file.resolve() == source_file # Expect the command to fail: We don't have the correct environment to execute it. # But this is no problem for our test, we only want to see the result of the compilation. assert subprocess.Popen(["python3", str(compiled_file)], shell=False, close_fds=True).wait() == 1 assert compiled_file.resolve() != source_file with compiled_file.open("rb") as f: assert f.read().startswith(importlib.util.MAGIC_NUMBER)
def _get_service(self, item: Optional[str]): from cmk.utils.type_defs import CheckPluginName from cmk.utils.check_utils import maincheckify from cmk.base.check_utils import Service description = self.info["service_description"] assert description, '%r is missing a service_description' % self.name if item is not None: assert "%s" in description, ("Missing '%%s' formatter in service description of %r" % self.name) description = description % item return Service( item=item, check_plugin_name=CheckPluginName(maincheckify(self.name)), description=description, parameters={}, )
def test_docker_container_diskstat_discovery( section_name: str, plugin_name: str, mocker, discovery_mode, string_table_0, fix_register, expected_item, ) -> None: agent_section = fix_register.agent_sections[SectionName(section_name)] plugin = fix_register.check_plugins[CheckPluginName(plugin_name)] assert plugin section_0_seconds = agent_section.parse_function(string_table_0) assert list( plugin.discovery_function( [discovery_mode], section_diskstat=section_0_seconds, section_multipath=None)) == [Service(item=expected_item)]