-
-
Notifications
You must be signed in to change notification settings - Fork 512
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a780739
commit 0589878
Showing
2 changed files
with
136 additions
and
0 deletions.
There are no files selected for viewing
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,79 @@ | ||
package testcontainers | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
// terminateOptions is a type that holds the options for terminating a container. | ||
type terminateOptions struct { | ||
ctx context.Context | ||
volumes []string | ||
} | ||
|
||
// TerminateOption is a type that represents an option for terminating a container. | ||
type TerminateOption func(*terminateOptions) | ||
|
||
// TerminateContainer calls [Container.Terminate] on the container if it is not nil. | ||
// | ||
// This should be called as a defer directly after [GenericContainer](...) | ||
// or a modules Run(...) to ensure the container is terminated when the | ||
// function ends. | ||
func TerminateContainer(container Container, options ...TerminateOption) error { | ||
if isNil(container) { | ||
return nil | ||
} | ||
|
||
c := &terminateOptions{ | ||
ctx: context.Background(), | ||
} | ||
|
||
for _, opt := range options { | ||
opt(c) | ||
} | ||
|
||
// TODO: Add a timeout when terminate supports it. | ||
err := container.Terminate(c.ctx) | ||
if !isCleanupSafe(err) { | ||
return fmt.Errorf("terminate: %w", err) | ||
} | ||
|
||
// Remove additional volumes if any. | ||
if len(c.volumes) == 0 { | ||
return nil | ||
} | ||
|
||
client, err := NewDockerClientWithOpts(c.ctx) | ||
if err != nil { | ||
return fmt.Errorf("docker client: %w", err) | ||
} | ||
|
||
defer client.Close() | ||
|
||
// Best effort to remove all volumes. | ||
var errs []error | ||
for _, volume := range c.volumes { | ||
if errRemove := client.VolumeRemove(c.ctx, volume, true); errRemove != nil { | ||
errs = append(errs, fmt.Errorf("volume remove %q: %w", volume, errRemove)) | ||
} | ||
} | ||
|
||
return errors.Join(errs...) | ||
} | ||
|
||
// isNil returns true if val is nil or an nil instance false otherwise. | ||
func isNil(val any) bool { | ||
if val == nil { | ||
return true | ||
} | ||
|
||
valueOf := reflect.ValueOf(val) | ||
switch valueOf.Kind() { | ||
case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: | ||
return valueOf.IsNil() | ||
default: | ||
return false | ||
} | ||
} |
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