def test_only_wrong_services(submit_result, get_status, get_services): logger = FakeLogger() message = 'themessage' trap_check_name = 'thetrapcheckname' instance = 'theinstance' services = [ { 'service_description': 'notthis' }, { 'service_description': 'orthis' }, ] get_services.return_value = services result = snmp_trap_handler.update_check_state( message=message, trap_check_name=trap_check_name, instance=instance, logger=logger, ) assert result == 3 for service in services: assert logger.string_appears_in( 'debug', ('considering service', service['service_description']), ) assert logger.string_appears_in('warn', ('service', 'not found')) get_services.assert_called_once_with(instance, 'nagios status')
def test_instance_finder_address_can_find_name(get_host_name): logger = FakeLogger() expected_name = 'thename' action = { 'instance': { 'finder': re.compile("^(?P<address>[a-z]+)$"), 'oid': 'something', }, } details = { 'something': 'anything', 'unimportant': 'notthis', } get_host_name.return_value = expected_name result = snmp_trap_handler.find_target_instance( action=action, details=details, message_source='notimportant', logger=logger, ) assert result == expected_name assert logger.string_appears_in('debug', ('look up', 'name')) assert logger.string_appears_in('debug', 'details finder found')
def test_oid_for_message_and_instance(): logger = FakeLogger() config_name = 'instance_and_message_oid' lookups = { 'instanceoid': 'lookedupinstance', 'messageoid': 'lookedupmessage', } oid_lookup = FakeOidLookup(lookups=lookups) result = snmp_trap_handler.determine_action( oid=config_name, oid_lookup=oid_lookup, logger=logger, ) expected_path = CONF_PATH.format(oid=config_name) assert logger.string_appears_in('debug', expected_path) assert logger.string_appears_in('debug', 'loading instance') assert logger.string_appears_in('debug', 'loading oid_for_message') assert result['instance'] == { 'oid': lookups['instanceoid'], 'finder': re.compile(u'testfinder'), } assert result['oid_for_message'] == lookups['messageoid']
def test_no_instance_finder_cannot_find_name(get_host_name): logger = FakeLogger() source_address = 'thesource' action = {} details = { 'unimportant': 'notthis', } get_host_name.return_value = None with pytest.raises(snmp_trap_handler.MonitoredHostNotFoundError): snmp_trap_handler.find_target_instance( action=action, details=details, message_source=source_address, logger=logger, ) assert logger.string_appears_in('debug', ('look up', 'name')) assert not logger.string_appears_in('debug', 'details finder found') assert logger.string_appears_in('error', 'no host found') get_host_name.assert_called_once_with(source_address)
def test_notification_failure(submit_result, get_status, get_services): logger = FakeLogger() message = 'themessage' trap_check_name = 'thetrapcheckname' instance = 'theinstance' services = [ { 'service_description': trap_check_name, 'current_state': '0' }, { 'service_description': 'notthis' }, ] get_services.return_value = services submit_result.side_effect = RuntimeError with pytest.raises(RuntimeError): snmp_trap_handler.update_check_state( message=message, trap_check_name=trap_check_name, instance=instance, logger=logger, ) for expected in ('correct service found', 'submitting check'): assert logger.string_appears_in('debug', expected) assert not logger.string_appears_in('warn', 'in progress')
def test_instance_finder_address_cannot_find_name(get_host_name): logger = FakeLogger() action = { 'instance': { 'finder': re.compile("^(?P<address>[a-z]+)$"), 'oid': 'something', }, } details = { 'something': 'anything', 'unimportant': 'notthis', } get_host_name.return_value = None with pytest.raises(snmp_trap_handler.MonitoredHostNotFoundError): snmp_trap_handler.find_target_instance( action=action, details=details, message_source='notimportant', logger=logger, ) assert logger.string_appears_in('debug', ('look up', 'name')) assert logger.string_appears_in('debug', 'details finder found') assert logger.string_appears_in('error', 'no host found')
def test_run_check_missing_ini(mock_print, exit, mock_subproc, mock_os, mock_get_types): logger = FakeLogger() script_path = 'something' target_type = 'thistargettype' hostname = 'thehost' oid = 'theoid' ignore_unknown = False mock_os.path.exists.return_value = False ini_names = ['yes', 'that'] ini_files = [ini_name + '.ini' for ini_name in ini_names] mock_os.listdir.return_value = BASE_DIR_LIST + ini_files mock_get_types.return_value = ini_names nagios_plugin_utils.run_check(script_path, target_type, hostname, oid, logger, ignore_unknown) mock_print_arg = mock_print.call_args_list[0][0][0].lower() assert 'target type' in mock_print_arg assert 'valid types' in mock_print_arg logger.string_appears_in('error', ('target type', 'valid types')) for ini_name in ini_names: assert ini_name in mock_print_arg logger.string_appears_in('error', ini_name) exit.assert_called_once_with(nagios_plugin_utils.STATUS_UNKNOWN)
def test_run_check_ignore_not_unknown(mock_print, exit, mock_subproc, mock_os, mock_get_types): logger = FakeLogger() script_path = 'something' target_type = 'thistargettype' hostname = 'thehost' oid = 'theoid' ignore_unknown = True mock_os.path.exists.return_value = True mock_os.path.isfile.return_value = True exit_status = 42 exit_output = 'badexitoutput' error = subprocess.CalledProcessError( exit_status, 'notarealcommand', exit_output, ) mock_subproc.side_effect = error nagios_plugin_utils.run_check(script_path, target_type, hostname, oid, logger, ignore_unknown) mock_print_arg = mock_print.call_args_list[0][0][0].lower() assert exit_output == mock_print_arg logger.string_appears_in('error', ('unknown or error', 'status', text_type(exit_status), 'output', exit_output)) exit.assert_called_once_with(exit_status)
def test_run_check_ignore_unknown(mock_print, exit, mock_subproc, mock_os, mock_get_types): logger = FakeLogger() script_path = 'something' target_type = 'thistargettype' hostname = 'thehost' oid = 'theoid' ignore_unknown = True mock_os.path.exists.return_value = True mock_os.path.isfile.return_value = True exit_status = 3 exit_output = 'badexitoutput' error = subprocess.CalledProcessError( exit_status, 'notarealcommand', exit_output, ) mock_subproc.side_effect = error result = nagios_plugin_utils.run_check(script_path, target_type, hostname, oid, logger, ignore_unknown) logger.string_appears_in('warn', ('unknown state', 'ignoring')) assert result is None assert mock_print.call_count == 0 assert exit.call_count == 0
def test_reaction_not_defined(nagios_utils, exit, snmp_utils, logging_utils): target_type = 'missing' trap_name = 'just_oid_for_message' lookups = deepcopy(BASE_LOOKUPS) lookups[BASIC_NOTIFICATION_TRAP_VALUE] = trap_name logger = FakeLogger() oid_lookup = FakeOidLookup(lookups=lookups) stdin = FakeStdin(deepcopy(BASIC_NOTIFICATION)) logging_utils.Logger.return_value = logger snmp_utils.OIDLookup.return_value = oid_lookup snmp_trap_handler.sys.stdin = stdin nagios_utils.get_target_type_for_instance.return_value = target_type snmp_trap_handler.main() logging_utils.Logger.assert_called_once_with( 'cloudify_nagios_snmp_trap_handler') assert logger.string_appears_in('info', ( 'trap', trap_name, 'from', NOTIFICATION_SOURCE, )) assert logger.string_appears_in('debug', 'looking up target type') assert logger.string_appears_in('debug', ('target type', target_type)) assert logger.string_appears_in('info', 'no reaction')
def test_found_already_notified(submit_result, get_status, get_services): logger = FakeLogger() message = 'themessage' trap_check_name = 'thetrapcheckname' instance = 'theinstance' services = [ { 'service_description': 'notthis' }, { 'service_description': trap_check_name, 'current_state': '2' }, ] get_services.return_value = services result = snmp_trap_handler.update_check_state( message=message, trap_check_name=trap_check_name, instance=instance, logger=logger, ) assert result == 1 assert logger.string_appears_in('debug', 'correct service found') assert logger.string_appears_in('warn', 'in progress') get_services.assert_called_once_with(instance, 'nagios status')
def test_no_instance_finder_can_find_name(get_host_name): logger = FakeLogger() expected_name = 'thename' source_address = 'thesource' action = {} details = { 'unimportant': 'notthis', } get_host_name.return_value = expected_name result = snmp_trap_handler.find_target_instance( action=action, details=details, message_source=source_address, logger=logger, ) assert result == expected_name assert logger.string_appears_in('debug', ('look up', 'name')) assert not logger.string_appears_in('debug', 'details finder found') get_host_name.assert_called_once_with(source_address)
def test_run_check_missing_script(mock_print, exit, mock_subproc, mock_os, mock_get_types): logger = FakeLogger() script_path = 'something' target_type = 'thistargettype' hostname = 'thehost' oid = 'theoid' ignore_unknown = False mock_os.path.exists.return_value = True mock_os.path.isfile.return_value = False nagios_plugin_utils.run_check(script_path, target_type, hostname, oid, logger, ignore_unknown) exist_check = mock_os.path.exists.call_args_list[0][0][0] assert exist_check.endswith(hashlib.md5(target_type).hexdigest() + '.ini') mock_print_arg = mock_print.call_args_list[0][0][0].lower() assert 'check_snmp' in mock_print_arg assert 'not found' in mock_print_arg logger.string_appears_in('error', ('check_snmp', 'not found')) exit.assert_called_once_with(nagios_plugin_utils.STATUS_UNKNOWN)
def test_no_result(mock_print, exit, thresholds, run_check, get_multi_float, calculate_mean, get_instance_addresses, get_host_address, generate_perfdata, generate_check_id, check_thresholds_and_exit, logging_utils): logger = FakeLogger() logging_utils.Logger.return_value = logger run_check_results = None, None run_check.side_effect = run_check_results returned_thresholds = 'thresholds' thresholds.return_value = returned_thresholds float_values = 1.5, 2.0 get_multi_float.return_value = float_values mean = 1.75 calculate_mean.return_value = mean old_calculate_mean = calculate_mean.APPROACHES['arithmetic_mean'] check_snmp_aggregate.APPROACHES['arithmetic_mean'] = calculate_mean instance_addresses = '192.0.2.5', '192.0.2.6' get_instance_addresses.return_value = instance_addresses host_addresses = ['addr1', 'addr2'] get_host_address.side_effect = host_addresses perfdata = 'performance_data' generate_perfdata.return_value = perfdata check_identifier = 'check_id' generate_check_id.return_value = check_identifier node = 'therealhost' oids = 'somefakeoid,other' target_type = 'thetypeoftarget' check_snmp_aggregate.main( ['--node', node, '--oids', oids, '--approach', 'arithmetic_mean', '--unknown', 'ignore', '--target-type', target_type] ) logger.string_appears_in('error', 'no values') mock_print_arg = mock_print.call_args_list[0][0][0].lower() assert 'no values' in mock_print_arg exit.assert_called_once_with(STATUS_UNKNOWN) check_snmp_aggregate.APPROACHES['arithmetic_mean'] = old_calculate_mean
def test_broken_instance(): logger = FakeLogger() config_name = 'broken_instance' with pytest.raises(KeyError): snmp_trap_handler.determine_action( oid=config_name, oid_lookup=mock.Mock(), logger=logger, ) expected_path = CONF_PATH.format(oid=config_name) assert logger.string_appears_in('debug', expected_path) assert logger.string_appears_in('debug', 'loading instance')
def test_oid_for_message_lookup_exception(): logger = FakeLogger() config_name = 'just_oid_for_message' oid_lookup = mock.Mock() oid_lookup.get.side_effect = RuntimeError with pytest.raises(RuntimeError): snmp_trap_handler.determine_action( oid=config_name, oid_lookup=oid_lookup, logger=logger, ) expected_path = CONF_PATH.format(oid=config_name) assert logger.string_appears_in('debug', expected_path) assert logger.string_appears_in('debug', 'loading oid_for_message')
def test_multi_oid(mock_print, exit, thresholds, run_check, get_perfdata, get_single_float, get_instance_rate_path, calculate_rate, check_thresholds_and_exit, logging_utils): logger = FakeLogger() hostname = 'therealhost' oid = 'somefakeoid,otheroid' target_type = 'thetypeoftarget' check_snmp_numeric.main( ['--hostname', hostname, '--oid', oid, '--target-type', target_type]) logger.string_appears_in('error', 'single oid') mock_print_arg = mock_print.call_args_list[0][0][0].lower() assert 'single oid' in mock_print_arg exit.assert_called_once_with(STATUS_UNKNOWN)
def test_missing_traps(): logger = FakeLogger() target_type = 'missingtraps' trap_value = 'test_trap' with pytest.raises(KeyError): snmp_trap_handler.determine_reaction( target_type=target_type, trap_value=trap_value, logger=logger, ) expected_path = CONF_PATH.format( target_type=hashlib.md5(target_type).hexdigest(), ) assert logger.string_appears_in('debug', expected_path) assert logger.string_appears_in('debug', 'loading reaction')
def test_no_reaction_found(): logger = FakeLogger() target_type = 'notrap' trap_value = 'test_trap' result = snmp_trap_handler.determine_reaction( target_type=target_type, trap_value=trap_value, logger=logger, ) expected_path = CONF_PATH.format( target_type=hashlib.md5(target_type).hexdigest(), ) assert logger.string_appears_in('debug', expected_path) assert logger.string_appears_in('debug', 'loading reaction') assert result is None
def test_low_higher_than_high(mock_print, exit): logger = FakeLogger() low_warning = 42 low_critical = 42 high_warning = 32 high_critical = 32 nagios_plugin_utils.validate_and_structure_thresholds( low_warning, low_critical, high_warning, high_critical, logger, ) mock_print_arg = mock_print.call_args_list[0][0][0] assert 'must be higher' in mock_print_arg logger.string_appears_in('error', 'must be higher') exit.assert_called_once_with(nagios_plugin_utils.STATUS_UNKNOWN)
def test_just_oid_for_message(): logger = FakeLogger() config_name = 'just_oid_for_message' oid_lookup = FakeOidLookup(default='looked_up_message_oid') result = snmp_trap_handler.determine_action( oid=config_name, oid_lookup=oid_lookup, logger=logger, ) expected_path = CONF_PATH.format(oid=config_name) assert logger.string_appears_in('debug', expected_path) assert not logger.string_appears_in('debug', 'loading instance') assert logger.string_appears_in('debug', 'loading oid_for_message') assert result['oid_for_message'] == 'looked_up_message_oid'
def test_verbose_reaction(nagios_utils, exit, snmp_utils, logging_utils, get_check_name): target_type = 'test_main_instance' trap_name = 'test_main_instance' check_name = 'thecheck' lookups = deepcopy(BASE_LOOKUPS) lookups[VERBOSE_NOTIFICATION_TRAP_VALUE] = trap_name logger = FakeLogger() oid_lookup = FakeOidLookup(lookups=lookups) stdin = FakeStdin(deepcopy(VERBOSE_NOTIFICATION)) logging_utils.Logger.return_value = logger snmp_utils.OIDLookup.return_value = oid_lookup snmp_trap_handler.sys.stdin = stdin nagios_utils.get_target_type_for_instance.return_value = target_type get_check_name.return_value = check_name nagios_utils.get_services_for_host.return_value = [{ "service_description": check_name, "current_state": "0", }] snmp_trap_handler.main() logging_utils.Logger.assert_called_once_with( 'cloudify_nagios_snmp_trap_handler') assert logger.string_appears_in('info', ( 'trap', trap_name, 'from', NOTIFICATION_SOURCE, )) assert logger.string_appears_in('debug', 'looking up target type') assert logger.string_appears_in('debug', ('target type', target_type)) assert logger.string_appears_in('info', ('reaction defined', 'updating', 'check')) exit.assert_called_once_with(0)
def test_not_yet_notified(submit_result, get_status, get_services): logger = FakeLogger() message = 'themessage' trap_check_name = 'thetrapcheckname' instance = 'theinstance' services = [ { 'service_description': trap_check_name, 'current_state': '0' }, { 'service_description': 'notthis' }, ] get_services.return_value = services result = snmp_trap_handler.update_check_state( message=message, trap_check_name=trap_check_name, instance=instance, logger=logger, ) assert result == 0 for expected in ('correct service found', 'submitting check', 'result submitted'): assert logger.string_appears_in('debug', expected) assert not logger.string_appears_in('warn', 'in progress') get_services.assert_called_once_with(instance, 'nagios status') submit_result.assert_called_once_with( host=instance, service=trap_check_name, status='2', output=message, )
def test_trap_in_details(): logger = FakeLogger() lookups = { 'system.sysUpTime.0': 'uptime', 'enterprises.52312.900.0.0.1': 'cloudifything', snmp_trap_handler.SNMP_TRAP_OID: 'snmptrap', 'snmp.1.1.4.1.0': 'snmptrap', } oid_lookup = FakeOidLookup(lookups=lookups) raw_details = [ { 'raw_oid': 'system.sysUpTime.0', 'value': '1234' }, { 'raw_oid': 'snmp.1.1.4.1.0', 'value': 'enterprises.52312.900.0.0.1' }, ] result = snmp_trap_handler.normalise_oids_and_get_trap_value( raw_details=raw_details, oid_lookup=oid_lookup, logger=logger, ) assert result == ( 'cloudifything', { lookups['system.sysUpTime.0']: '1234', lookups['snmp.1.1.4.1.0']: 'enterprises.52312.900.0.0.1', }, ) assert logger.string_appears_in('debug', ('trap identity', 'cloudifything')) assert logger.string_appears_in('debug', ('uptime', '1234'))
def test_no_trap(): logger = FakeLogger() lookups = { 'system.sysUpTime.0': 'uptime', } oid_lookup = FakeOidLookup(lookups=lookups) raw_details = [ { 'raw_oid': 'system.sysUpTime.0', 'value': '1234' }, ] result = snmp_trap_handler.normalise_oids_and_get_trap_value( raw_details=raw_details, oid_lookup=oid_lookup, logger=logger, ) assert result == (None, {lookups['system.sysUpTime.0']: '1234'}) assert not logger.string_appears_in('debug', 'trap identity') assert logger.string_appears_in('debug', ('uptime', '1234'))
def test_run_check_no_inis(mock_print, exit, mock_subproc, mock_os, mock_get_types): logger = FakeLogger() script_path = 'something' target_type = 'thistargettype' hostname = 'thehost' oid = 'theoid' ignore_unknown = False mock_os.path.exists.return_value = False mock_os.listdir.return_value = BASE_DIR_LIST mock_get_types.return_value = [] nagios_plugin_utils.run_check(script_path, target_type, hostname, oid, logger, ignore_unknown) mock_print_arg = mock_print.call_args_list[0][0][0].lower() assert 'target type' in mock_print_arg assert 'valid types' in mock_print_arg assert 'none' in mock_print_arg logger.string_appears_in('error', ('target type', 'valid types', 'none')) exit.assert_called_once_with(nagios_plugin_utils.STATUS_UNKNOWN)
def test_generate_message_without_oid(): logger = FakeLogger() trap_value = 'thetrap' action = {} details = {} expected_prefix = snmp_trap_handler.TRAP_RECEIVED_PREFIX.format( oid=trap_value, ).lower() result = snmp_trap_handler.generate_check_message(trap_value, details, action, logger) result = result.lower() for component in (expected_prefix, 'no message oid', trap_value): assert component in result assert logger.string_appears_in('debug', component)
def test_missing_action(): logger = FakeLogger() config_name = 'missing' result = snmp_trap_handler.determine_action( oid=config_name, oid_lookup=mock.Mock(), logger=logger, ) assert result is None expected_path = CONF_PATH.format(oid=config_name) assert logger.string_appears_in('debug', expected_path) assert 'not found' in logger.messages['warn'][-1]
def test_check_name(): logger = FakeLogger() target_type = 'target' trap_value = 'trap' expected = '{target_type}_instances:SNMPTRAP {trap}'.format( target_type=target_type, trap=trap_value, ) result = snmp_trap_handler.get_check_name(target_type, trap_value, logger) assert result == expected assert logger.string_appears_in('debug', ('check name', 'is', expected.lower()))
def test_empty_action(): logger = FakeLogger() config_name = 'empty' with pytest.raises(ValueError): snmp_trap_handler.determine_action( oid=config_name, oid_lookup=mock.Mock(), logger=logger, ) expected_path = CONF_PATH.format(oid=config_name) assert logger.string_appears_in('debug', expected_path) assert 'not' in logger.messages['exception'][-1] assert 'JSON' in logger.messages['exception'][-1] assert 'empty' in logger.messages['exception'][-1]