check_http and check_curl: custom timeout return state (#2266)
Some checks failed
CodeQL / Analyze (push) Has been cancelled
Spellcheck / codespell (push) Has been cancelled
Tests / Running unit and integrationt tests (push) Has been cancelled
Tests / Running rpm build test on almalinux:9 (push) Has been cancelled
Tests / Running rpm build test on fedora:latest (push) Has been cancelled
Tests / Running rpm build test on rockylinux:8 (push) Has been cancelled
Tests Debian:Testing and Fedora:Rawhide / Running unit and integrationt tests (push) Has been cancelled
Tests Debian:Testing and Fedora:Rawhide / Running rpm build test on fedora:rawhide (push) Has been cancelled

check_curl + check_http:
 hdd cli argument to return custom states on timeout

---------

Co-authored-by: Ahmet Oeztuerk <Ahmet.Oeztuerk@consol.de>
This commit is contained in:
inqrphl 2026-05-19 16:01:43 +02:00 committed by GitHub
parent 5ccce85495
commit 178e9a02e3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 86 additions and 7 deletions

View file

@ -273,9 +273,17 @@ mp_subcheck check_http(const check_curl_config config, check_curl_working_state
/* Curl errors, result in critical Nagios state */
if (res != CURLE_OK) {
xasprintf(&sc_curl.output, _("Error while performing connection: cURL returned %d - %s"),
res, errbuf[0] ? errbuf : curl_easy_strerror(res));
sc_curl = mp_set_subcheck_state(sc_curl, STATE_CRITICAL);
/* Custom handling for timeouts, state might be set to non CRITICAL */
if (res == CURLE_OPERATION_TIMEDOUT) {
xasprintf(&sc_curl.output, _("cURL returned %d - %s"), res,
errbuf[0] ? errbuf : curl_easy_strerror(res));
sc_curl = mp_set_subcheck_state(sc_curl, config.on_timeout_result_state);
} else {
xasprintf(&sc_curl.output,
_("Error while performing connection: cURL returned %d - %s"), res,
errbuf[0] ? errbuf : curl_easy_strerror(res));
sc_curl = mp_set_subcheck_state(sc_curl, STATE_CRITICAL);
}
mp_add_subcheck_to_subcheck(&sc_result, sc_curl);
return sc_result;
}
@ -890,6 +898,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
STATE_REGEX,
OUTPUT_FORMAT,
NO_PROXY,
TIMEOUT_RESULT,
};
static struct option longopts[] = {
@ -939,6 +948,7 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
{"cookie-jar", required_argument, 0, COOKIE_JAR},
{"haproxy-protocol", no_argument, 0, HAPROXY_PROTOCOL},
{"output-format", required_argument, 0, OUTPUT_FORMAT},
{"timeout-result", required_argument, 0, TIMEOUT_RESULT},
{0, 0, 0, 0}};
check_curl_config_wrapper result = {
@ -1004,6 +1014,21 @@ check_curl_config_wrapper process_arguments(int argc, char **argv) {
result.config.curl_config.socket_timeout = (int)strtol(optarg, NULL, 10);
}
break;
case TIMEOUT_RESULT:
if (!strcmp(optarg, "0") || !strcasecmp(optarg, "ok")) {
result.config.on_timeout_result_state = STATE_OK;
} else if (!strcmp(optarg, "1") || !strcasecmp(optarg, "warning")) {
result.config.on_timeout_result_state = STATE_WARNING;
} else if (!strcmp(optarg, "2") || !strcasecmp(optarg, "critical")) {
result.config.on_timeout_result_state = STATE_CRITICAL;
} else if (!strcmp(optarg, "3") || !strcasecmp(optarg, "unknown")) {
result.config.on_timeout_result_state = STATE_UNKNOWN;
} else {
usage2(_("Invalid timeout-result state option, give either a return code or state "
"name in lowercase"),
optarg);
}
break;
case 'c': /* critical time threshold */
{
mp_range_parsed critical_range = mp_parse_range_string(optarg);
@ -1701,6 +1726,10 @@ void print_help(void) {
printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
printf(" %s\n", "--timeout-result=ok|warning|critical|unknown|0|1|2|3");
printf(" %s\n", _("Timeouts default to returning STATE_CRITICAL."));
printf(" %s\n", _("This argument changes the return state on timeouts."));
printf(UT_VERBOSE);
printf(UT_OUTPUT_FORMAT);

View file

@ -755,6 +755,7 @@ check_curl_config check_curl_config_init(void) {
.header_expect = "",
.on_redirect_result_state = STATE_OK,
.on_redirect_dependent = false,
.on_timeout_result_state = STATE_CRITICAL,
.show_extended_perfdata = false,
.show_body = false,

View file

@ -113,9 +113,12 @@ typedef struct {
mp_state_enum on_redirect_result_state;
bool on_redirect_dependent;
mp_state_enum on_timeout_result_state;
bool show_extended_perfdata;
bool show_body;
bool output_format_is_set;
mp_output_format output_format;
} check_curl_config;

View file

@ -205,7 +205,8 @@ bool process_arguments(int argc, char **argv) {
SNI_OPTION,
MAX_REDIRS_OPTION,
CONTINUE_AFTER_CHECK_CERT,
STATE_REGEX
STATE_REGEX,
TIMEOUT_RESULT
};
int option = 0;
@ -247,6 +248,7 @@ bool process_arguments(int argc, char **argv) {
{"extended-perfdata", no_argument, 0, 'E'},
{"show-body", no_argument, 0, 'B'},
{"max-redirs", required_argument, 0, MAX_REDIRS_OPTION},
{"timeout-result", required_argument, 0, TIMEOUT_RESULT},
{0, 0, 0, 0}};
if (argc < 2) {
@ -298,6 +300,21 @@ bool process_arguments(int argc, char **argv) {
socket_timeout = atoi(optarg);
}
break;
case TIMEOUT_RESULT:
if (!strcmp(optarg, "0") || !strcasecmp(optarg, "ok")) {
socket_timeout_state = STATE_OK;
} else if (!strcmp(optarg, "1") || !strcasecmp(optarg, "warning")) {
socket_timeout_state = STATE_WARNING;
} else if (!strcmp(optarg, "2") || !strcasecmp(optarg, "critical")) {
socket_timeout_state = STATE_CRITICAL;
} else if (!strcmp(optarg, "3") || !strcasecmp(optarg, "unknown")) {
socket_timeout_state = STATE_UNKNOWN;
} else {
usage2(_("Invalid timeout-result state option, give either a return code or state "
"name in lowercase"),
optarg);
}
break;
case 'c': /* critical time threshold */
critical_thresholds = optarg;
break;
@ -1032,7 +1049,7 @@ int check_http(void) {
printf("SSL initialized\n");
}
if (result != STATE_OK) {
die(STATE_CRITICAL, _("HTTP CRITICAL - SSL error\n"));
die(STATE_CRITICAL, _("HTTP CRITICAL - SSL error\n"));
}
microsec_ssl = deltime(tv_temp);
elapsed_time_ssl = (double)microsec_ssl / 1.0e6;
@ -1883,6 +1900,10 @@ void print_help(void) {
printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
printf(" %s\n", "--timeout-result=ok|warning|critical|unknown|0|1|2|3");
printf(" %s\n", _("Timeouts default to returning STATE_CRITICAL."));
printf(" %s\n", _("This argument changes the return state on timeouts."));
printf(UT_VERBOSE);
printf("\n");

View file

@ -13,7 +13,7 @@ use vars qw($tests $has_ipv6);
BEGIN {
use NPTest;
$has_ipv6 = NPTest::has_ipv6();
$tests = $has_ipv6 ? 57 : 92;
$tests = $has_ipv6 ? 65 : 100;
plan tests => $tests;
}
@ -69,7 +69,32 @@ $res = NPTest->testCmd(
);
cmp_ok( $res->return_code, '==', 2, "Webserver $host_nonresponsive not responding" );
# was CRITICAL only, but both check_curl and check_http print HTTP CRITICAL (puzzle?!)
like( $res->output, "/cURL returned 28 - Connection timed out after/", "Output OK");
like( $res->output, "/cURL returned 28 - (Connection|Operation) timed out after/", "Output OK");
# timeout return results can be changed using --timeout-result option
$res = NPTest->testCmd(
"./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3 --timeout-result ok"
);
like( $res->output, "/cURL returned 28 - (Connection|Operation) timed out after/", "Output OK");
cmp_ok( $res->return_code, "==", 0, "Return code is correct due argument: --timeout-result ok");
$res = NPTest->testCmd(
"./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3 --timeout-result warning"
);
like( $res->output, "/cURL returned 28 - (Connection|Operation) timed out after/", "Output OK");
cmp_ok( $res->return_code, "==", 1, "Return code is correct due argument: --timeout-result warning");
$res = NPTest->testCmd(
"./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3 --timeout-result 2"
);
like( $res->output, "/cURL returned 28 - (Connection|Operation) timed out after/", "Output OK");
cmp_ok( $res->return_code, "==", 2, "Return code is correct due argument: --timeout-result 2");
$res = NPTest->testCmd(
"./$plugin $host_nonresponsive -wt 1 -ct 2 -t 3 --timeout-result 3"
);
like( $res->output, "/cURL returned 28 - (Connection|Operation) timed out after/", "Output OK");
cmp_ok( $res->return_code, "==", 3, "Return code is correct due argument: --timeout-result 3");
$res = NPTest->testCmd(
"./$plugin $hostname_invalid -wt 1 -ct 2"