-
-
Notifications
You must be signed in to change notification settings - Fork 209
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make
HealthCheckWaitStrategy
event based (#789)
- Loading branch information
1 parent
3bafc47
commit 6152416
Showing
5 changed files
with
68 additions
and
18 deletions.
There are no files selected for viewing
12 changes: 12 additions & 0 deletions
12
...ages/testcontainers/fixtures/docker-compose/docker-compose-with-healthcheck-unhealthy.yml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
version: "3.5" | ||
|
||
services: | ||
container: | ||
image: cristianrgreco/testcontainer:1.1.14 | ||
ports: | ||
- 8080 | ||
healthcheck: | ||
test: "curl -f http://localhost:8081/hello-world || exit 1" | ||
timeout: 3s | ||
interval: 1s | ||
retries: 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
50 changes: 33 additions & 17 deletions
50
packages/testcontainers/src/wait-strategies/health-check-wait-strategy.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,47 @@ | ||
import Dockerode from "dockerode"; | ||
import { AbstractWaitStrategy } from "./wait-strategy"; | ||
import { IntervalRetry, log } from "../common"; | ||
import { log } from "../common"; | ||
import { getContainerRuntimeClient } from "../container-runtime"; | ||
|
||
export class HealthCheckWaitStrategy extends AbstractWaitStrategy { | ||
public async waitUntilReady(container: Dockerode.Container): Promise<void> { | ||
log.debug(`Waiting for health check...`, { containerId: container.id }); | ||
|
||
const client = await getContainerRuntimeClient(); | ||
const containerEvents = await client.container.events(container, ["health_status"]); | ||
|
||
const status = await new IntervalRetry<string | undefined, Error>(100).retryUntil( | ||
async () => (await client.container.inspect(container)).State.Health?.Status, | ||
(healthCheckStatus) => healthCheckStatus === "healthy" || healthCheckStatus === "unhealthy", | ||
() => { | ||
const timeout = this.startupTimeout; | ||
const message = `Health check not healthy after ${timeout}ms`; | ||
return new Promise((resolve, reject) => { | ||
const timeout = setTimeout(() => { | ||
const message = `Health check not healthy after ${this.startupTimeout}ms`; | ||
log.error(message, { containerId: container.id }); | ||
throw new Error(message); | ||
}, | ||
this.startupTimeout | ||
); | ||
containerEvents.destroy(); | ||
reject(new Error(message)); | ||
}, this.startupTimeout); | ||
|
||
const onTerminalState = () => { | ||
clearTimeout(timeout); | ||
containerEvents.destroy(); | ||
log.debug(`Health check wait strategy complete`, { containerId: container.id }); | ||
}; | ||
|
||
containerEvents.on("data", (data) => { | ||
const parsedData = JSON.parse(data); | ||
|
||
if (status !== "healthy") { | ||
const message = `Health check failed: ${status}`; | ||
log.error(message, { containerId: container.id }); | ||
throw new Error(message); | ||
} | ||
const status = | ||
parsedData.status.split(":").length === 2 | ||
? parsedData.status.split(":")[1].trim() // Docker | ||
: parsedData.HealthStatus; // Podman | ||
|
||
log.debug(`Health check wait strategy complete`, { containerId: container.id }); | ||
if (status === "healthy") { | ||
resolve(); | ||
onTerminalState(); | ||
} else if (status === "unhealthy") { | ||
const message = `Health check failed: ${status}`; | ||
log.error(message, { containerId: container.id }); | ||
reject(new Error(message)); | ||
onTerminalState(); | ||
} | ||
}); | ||
}); | ||
} | ||
} |