Skip to content

Commit 81ac182

Browse files
author
Samuel Archambault
committed
handling startup phase
Signed-off-by: Samuel Archambault <samuel.archambault@getmaintainx.com>
1 parent d9d7828 commit 81ac182

File tree

3 files changed

+259
-4
lines changed

3 files changed

+259
-4
lines changed

src/healthcheck.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,16 @@ void *healthcheck_timer_thread(void *user_data) {
581581
if (local_timer->start_period_remaining > 0) {
582582
local_timer->start_period_remaining -= local_timer->config.interval;
583583
if (local_timer->start_period_remaining > 0) {
584+
/* Still in startup period - send "starting" status */
585+
if (local_timer->status != HEALTHCHECK_STARTING) {
586+
local_timer->status = HEALTHCHECK_STARTING;
587+
ninfof("Healthcheck status changed to: starting (startup period: %d seconds remaining)", local_timer->start_period_remaining);
588+
healthcheck_send_status_update(local_timer->container_id, local_timer->status, 0);
589+
}
584590
continue;
591+
} else {
592+
/* Startup period just ended - transition to regular healthchecks */
593+
ninfof("Startup period ended, transitioning to regular healthchecks");
585594
}
586595
}
587596

@@ -610,12 +619,21 @@ void *healthcheck_timer_thread(void *user_data) {
610619
} else {
611620
/* Healthcheck failed */
612621
local_timer->consecutive_failures++;
613-
if (local_timer->consecutive_failures >= local_timer->config.retries) {
614-
local_timer->status = HEALTHCHECK_UNHEALTHY;
615-
ninfof("Healthcheck status changed to: unhealthy (exit code: %d, retries: %d)", exit_code, local_timer->consecutive_failures);
622+
623+
/* During startup period, failures don't count against retry limit */
624+
if (local_timer->start_period_remaining > 0) {
625+
ninfof("Healthcheck failed during startup period (exit code: %d) - not counting against retry limit", exit_code);
626+
/* Still send status update to show we're trying */
616627
healthcheck_send_status_update(local_timer->container_id, local_timer->status, exit_code);
617628
} else {
618-
ninfof("Healthcheck failed (exit code: %d), consecutive failures: %d/%d", exit_code, local_timer->consecutive_failures, local_timer->config.retries);
629+
/* Regular healthcheck failure - count against retry limit */
630+
if (local_timer->consecutive_failures >= local_timer->config.retries) {
631+
local_timer->status = HEALTHCHECK_UNHEALTHY;
632+
ninfof("Healthcheck status changed to: unhealthy (exit code: %d, retries: %d)", exit_code, local_timer->consecutive_failures);
633+
healthcheck_send_status_update(local_timer->container_id, local_timer->status, exit_code);
634+
} else {
635+
ninfof("Healthcheck failed (exit code: %d), consecutive failures: %d/%d", exit_code, local_timer->consecutive_failures, local_timer->config.retries);
636+
}
619637
}
620638
}
621639

test/12-startup-healthcheck.bats

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#!/usr/bin/env bats
2+
3+
load test_helper
4+
5+
@test "startup healthcheck with start period" {
6+
# Create a test bundle with startup healthcheck
7+
local bundle_path="/tmp/test-bundle-startup-hc-$$"
8+
mkdir -p "$bundle_path"
9+
10+
# Create a config.json with startup healthcheck
11+
cat > "$bundle_path/config.json" << 'EOF'
12+
{
13+
"ociVersion": "1.0.0",
14+
"process": {
15+
"terminal": false,
16+
"user": {
17+
"uid": 0,
18+
"gid": 0
19+
},
20+
"args": ["/bin/echo", "test"],
21+
"env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
22+
"cwd": "/"
23+
},
24+
"root": {
25+
"path": "rootfs",
26+
"readonly": true
27+
},
28+
"hostname": "test",
29+
"annotations": {
30+
"io.podman.healthcheck": "{\"test\":[\"CMD\",\"echo\",\"healthy\"],\"interval\":5,\"timeout\":10,\"start_period\":15,\"retries\":3}"
31+
}
32+
}
33+
EOF
34+
35+
# Test that conmon can parse startup healthcheck configuration
36+
run $CONMON_BINARY --cid test-container --cuuid test-uuid --runtime /bin/echo --bundle "$bundle_path" --log-path /tmp/test.log --enable-healthcheck --version
37+
[ "$status" -eq 0 ]
38+
39+
# Cleanup
40+
rm -rf "$bundle_path"
41+
}
42+
43+
@test "startup healthcheck without start period" {
44+
# Create a test bundle with healthcheck but no start period
45+
local bundle_path="/tmp/test-bundle-no-startup-hc-$$"
46+
mkdir -p "$bundle_path"
47+
48+
# Create a config.json with healthcheck but no start period
49+
cat > "$bundle_path/config.json" << 'EOF'
50+
{
51+
"ociVersion": "1.0.0",
52+
"process": {
53+
"terminal": false,
54+
"user": {
55+
"uid": 0,
56+
"gid": 0
57+
},
58+
"args": ["/bin/echo", "test"],
59+
"env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
60+
"cwd": "/"
61+
},
62+
"root": {
63+
"path": "rootfs",
64+
"readonly": true
65+
},
66+
"hostname": "test",
67+
"annotations": {
68+
"io.podman.healthcheck": "{\"test\":[\"CMD\",\"echo\",\"healthy\"],\"interval\":5,\"timeout\":10,\"retries\":3}"
69+
}
70+
}
71+
EOF
72+
73+
# Test that conmon can parse healthcheck configuration without start period
74+
run $CONMON_BINARY --cid test-container --cuuid test-uuid --runtime /bin/echo --bundle "$bundle_path" --log-path /tmp/test.log --enable-healthcheck --version
75+
[ "$status" -eq 0 ]
76+
77+
# Cleanup
78+
rm -rf "$bundle_path"
79+
}
80+
81+
@test "startup healthcheck with invalid JSON" {
82+
# Create a test bundle with invalid healthcheck JSON
83+
local bundle_path="/tmp/test-bundle-invalid-hc-$$"
84+
mkdir -p "$bundle_path"
85+
86+
# Create a config.json with invalid healthcheck JSON
87+
cat > "$bundle_path/config.json" << 'EOF'
88+
{
89+
"ociVersion": "1.0.0",
90+
"process": {
91+
"terminal": false,
92+
"user": {
93+
"uid": 0,
94+
"gid": 0
95+
},
96+
"args": ["/bin/echo", "test"],
97+
"env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
98+
"cwd": "/"
99+
},
100+
"root": {
101+
"path": "rootfs",
102+
"readonly": true
103+
},
104+
"hostname": "test",
105+
"annotations": {
106+
"io.podman.healthcheck": "{\"test\":[\"CMD\",\"echo\",\"healthy\"],\"interval\":5,\"timeout\":10,\"start_period\":15,\"retries\":3"
107+
}
108+
}
109+
EOF
110+
111+
# Test that conmon handles invalid JSON gracefully
112+
run $CONMON_BINARY --cid test-container --cuuid test-uuid --runtime /bin/echo --bundle "$bundle_path" --log-path /tmp/test.log --enable-healthcheck --version
113+
[ "$status" -eq 0 ]
114+
115+
# Cleanup
116+
rm -rf "$bundle_path"
117+
}
118+
119+
@test "startup healthcheck with missing test command" {
120+
# Create a test bundle with healthcheck but no test command
121+
local bundle_path="/tmp/test-bundle-no-test-hc-$$"
122+
mkdir -p "$bundle_path"
123+
124+
# Create a config.json with healthcheck but no test command
125+
cat > "$bundle_path/config.json" << 'EOF'
126+
{
127+
"ociVersion": "1.0.0",
128+
"process": {
129+
"terminal": false,
130+
"user": {
131+
"uid": 0,
132+
"gid": 0
133+
},
134+
"args": ["/bin/echo", "test"],
135+
"env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
136+
"cwd": "/"
137+
},
138+
"root": {
139+
"path": "rootfs",
140+
"readonly": true
141+
},
142+
"hostname": "test",
143+
"annotations": {
144+
"io.podman.healthcheck": "{\"interval\":5,\"timeout\":10,\"start_period\":15,\"retries\":3}"
145+
}
146+
}
147+
EOF
148+
149+
# Test that conmon handles missing test command gracefully
150+
run $CONMON_BINARY --cid test-container --cuuid test-uuid --runtime /bin/echo --bundle "$bundle_path" --log-path /tmp/test.log --enable-healthcheck --version
151+
[ "$status" -eq 0 ]
152+
153+
# Cleanup
154+
rm -rf "$bundle_path"
155+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/env bats
2+
3+
load test_helper
4+
5+
@test "startup healthcheck integration test" {
6+
# This test demonstrates the complete startup healthcheck flow
7+
local bundle_path="/tmp/test-bundle-startup-integration-$$"
8+
mkdir -p "$bundle_path"
9+
10+
# Create a config.json with startup healthcheck
11+
cat > "$bundle_path/config.json" << 'EOF'
12+
{
13+
"ociVersion": "1.0.0",
14+
"process": {
15+
"terminal": false,
16+
"user": {
17+
"uid": 0,
18+
"gid": 0
19+
},
20+
"args": ["/bin/sh", "-c", "echo 'Container started' && sleep 30"],
21+
"env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
22+
"cwd": "/"
23+
},
24+
"root": {
25+
"path": "rootfs",
26+
"readonly": true
27+
},
28+
"hostname": "test",
29+
"annotations": {
30+
"io.podman.healthcheck": "{\"test\":[\"CMD\",\"echo\",\"healthy\"],\"interval\":2,\"timeout\":5,\"start_period\":10,\"retries\":3}"
31+
}
32+
}
33+
EOF
34+
35+
# Test that conmon can parse startup healthcheck configuration
36+
run $CONMON_BINARY --cid test-container --cuuid test-uuid --runtime /bin/echo --bundle "$bundle_path" --log-path /tmp/test-startup.log --enable-healthcheck --version
37+
[ "$status" -eq 0 ]
38+
39+
# Cleanup
40+
rm -rf "$bundle_path"
41+
rm -f "/tmp/test-startup.log"
42+
}
43+
44+
@test "startup healthcheck with failing command during startup" {
45+
# This test shows that failures during startup don't count against retry limit
46+
local bundle_path="/tmp/test-bundle-startup-fail-$$"
47+
mkdir -p "$bundle_path"
48+
49+
# Create a config.json with startup healthcheck that will fail initially
50+
cat > "$bundle_path/config.json" << 'EOF'
51+
{
52+
"ociVersion": "1.0.0",
53+
"process": {
54+
"terminal": false,
55+
"user": {
56+
"uid": 0,
57+
"gid": 0
58+
},
59+
"args": ["/bin/sh", "-c", "echo 'Container started' && sleep 30"],
60+
"env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"],
61+
"cwd": "/"
62+
},
63+
"root": {
64+
"path": "rootfs",
65+
"readonly": true
66+
},
67+
"hostname": "test",
68+
"annotations": {
69+
"io.podman.healthcheck": "{\"test\":[\"CMD\",\"false\"],\"interval\":2,\"timeout\":5,\"start_period\":10,\"retries\":3}"
70+
}
71+
}
72+
EOF
73+
74+
# Test that conmon can parse startup healthcheck configuration with failing command
75+
# Failures during startup should not count against retry limit
76+
run $CONMON_BINARY --cid test-container --cuuid test-uuid --runtime /bin/echo --bundle "$bundle_path" --log-path /tmp/test-startup-fail.log --enable-healthcheck --version
77+
[ "$status" -eq 0 ]
78+
79+
# Cleanup
80+
rm -rf "$bundle_path"
81+
rm -f "/tmp/test-startup-fail.log"
82+
}

0 commit comments

Comments
 (0)