feat: wait container healthy state (#467)

This commit is contained in:
Boris HUISGEN 2022-11-02 09:19:45 +01:00 committed by GitHub
parent 4eb65f64db
commit e1cf4151a1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 4 deletions

View file

@ -94,6 +94,8 @@ resource "docker_image" "ubuntu" {
- `user` (String) User used for run the first process. Format is `user` or `user:group` which user and group can be passed literraly or by name.
- `userns_mode` (String) Sets the usernamespace mode for the container when usernamespace remapping option is enabled.
- `volumes` (Block Set) Spec for mounting volumes in the container. (see [below for nested schema](#nestedblock--volumes))
- `wait` (Boolean) If `true`, then the Docker container is waited for being healthy state after creation. If `false`, then the container health state is not checked. Defaults to `false`.
- `wait_timeout` (Number) The timeout in seconds to wait the container to be healthy after creation. Defaults to `60`.
- `working_dir` (String) The working directory for commands to run in.
### Read-Only

View file

@ -64,6 +64,20 @@ func resourceDockerContainer() *schema.Resource {
Optional: true,
},
"wait": {
Type: schema.TypeBool,
Description: "If `true`, then the Docker container is waited for being healthy state after creation. If `false`, then the container health state is not checked. Defaults to `false`.",
Default: false,
Optional: true,
},
"wait_timeout": {
Type: schema.TypeInt,
Description: "The timeout in seconds to wait the container to be healthy after creation. Defaults to `60`.",
Default: 60,
Optional: true,
},
"attach": {
Type: schema.TypeBool,
Description: "If `true` attach to the container after its creation and waits the end of its execution. Defaults to `false`.",

View file

@ -39,6 +39,7 @@ var (
errContainerFailedToBeDeleted = errors.New("container failed to be deleted")
errContainerExitedImmediately = errors.New("container exited immediately")
errContainerFailedToBeInRunningState = errors.New("container failed to be in running state")
errContainerFailedToBeInHealthyState = errors.New("container failed to be in healthy state")
)
// NOTE mavogel: we keep this global var for tracking
@ -506,6 +507,39 @@ func resourceDockerContainerCreate(ctx context.Context, d *schema.ResourceData,
if err := client.ContainerStart(ctx, retContainer.ID, options); err != nil {
return diag.Errorf("Unable to start container: %s", err)
}
if d.Get("wait").(bool) {
waitForHealthyState := func(result chan<- error) {
for {
infos, err := client.ContainerInspect(ctx, retContainer.ID)
if err != nil {
result <- fmt.Errorf("error inspecting container state: %s", err)
}
if infos.State.Health.Status == types.Healthy {
log.Printf("[DEBUG] container state is healthy")
break
}
log.Printf("[DEBUG] waiting for container healthy state")
time.Sleep(time.Second)
}
result <- nil
}
ctx, cancel := context.WithTimeout(ctx, time.Duration(d.Get("wait_timeout").(int))*time.Second)
defer cancel()
result := make(chan error, 1)
go waitForHealthyState(result)
select {
case <-ctx.Done():
log.Printf("[ERROR] Container %s failed to be in healthy state in time", retContainer.ID)
return diag.FromErr(errContainerFailedToBeInHealthyState)
case err := <-result:
if err != nil {
return diag.FromErr(err)
}
}
}
}
if d.Get("attach").(bool) {

View file

@ -89,6 +89,8 @@ func TestAccDockerContainer_basic(t *testing.T) {
"restart",
"rm",
"start",
"wait",
"wait_timeout",
"container_logs",
"destroy_grace_seconds",
"upload",
@ -132,6 +134,8 @@ func TestAccDockerContainer_init(t *testing.T) {
"restart",
"rm",
"start",
"wait",
"wait_timeout",
"container_logs",
"destroy_grace_seconds",
"upload",
@ -962,12 +966,12 @@ func TestAccDockerContainer_multipleUploadContentsConfig(t *testing.T) {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = docker_image.foo.image_id
must_run = "false"
upload {
content = "foobar"
content_base64 = base64encode("barbaz")
@ -993,12 +997,12 @@ func TestAccDockerContainer_noUploadContentsConfig(t *testing.T) {
name = "nginx:latest"
keep_locally = true
}
resource "docker_container" "foo" {
name = "tf-test"
image = docker_image.foo.image_id
must_run = "false"
upload {
file = "/terraform/test1.txt"
executable = true