diff --git a/docker.go b/docker.go index 9649eb1e..c6651522 100644 --- a/docker.go +++ b/docker.go @@ -273,22 +273,13 @@ func (c *DockerContainer) Terminate(ctx context.Context) error { defer c.provider.client.Close() - err := c.terminatingHook(ctx) - if err != nil { - return err - } - - err = c.provider.client.ContainerRemove(ctx, c.GetContainerID(), container.RemoveOptions{ - RemoveVolumes: true, - Force: true, - }) - if err != nil { - return err - } - - err = c.terminatedHook(ctx) - if err != nil { - return err + errs := []error{ + c.terminatingHook(ctx), + c.provider.client.ContainerRemove(ctx, c.GetContainerID(), container.RemoveOptions{ + RemoveVolumes: true, + Force: true, + }), + c.terminatedHook(ctx), } if c.imageWasBuilt && !c.keepBuiltImage { @@ -296,14 +287,12 @@ func (c *DockerContainer) Terminate(ctx context.Context) error { Force: true, PruneChildren: true, }) - if err != nil { - return err - } + errs = append(errs, err) } c.sessionID = "" c.isRunning = false - return nil + return errors.Join(errs...) } // update container raw info diff --git a/lifecycle.go b/lifecycle.go index fc1b28e1..407fac50 100644 --- a/lifecycle.go +++ b/lifecycle.go @@ -2,6 +2,7 @@ package testcontainers import ( "context" + "errors" "fmt" "io" "strings" @@ -209,62 +210,64 @@ var defaultReadinessHook = func() ContainerLifecycleHooks { // creatingHook is a hook that will be called before a container is created. func (req ContainerRequest) creatingHook(ctx context.Context) error { - for _, lifecycleHooks := range req.LifecycleHooks { - err := lifecycleHooks.Creating(ctx)(req) - if err != nil { - return err - } + errs := make([]error, len(req.LifecycleHooks)) + for i, lifecycleHooks := range req.LifecycleHooks { + errs[i] = lifecycleHooks.Creating(ctx)(req) } - return nil + return errors.Join(errs...) } -// createdHook is a hook that will be called after a container is created +// createdHook is a hook that will be called after a container is created. func (c *DockerContainer) createdHook(ctx context.Context) error { - for _, lifecycleHooks := range c.lifecycleHooks { - err := containerHookFn(ctx, lifecycleHooks.PostCreates)(c) - if err != nil { - return err - } + errs := make([]error, len(c.lifecycleHooks)) + for i, lifecycleHooks := range c.lifecycleHooks { + errs[i] = containerHookFn(ctx, lifecycleHooks.PostCreates)(c) } - return nil + return errors.Join(errs...) } -// startingHook is a hook that will be called before a container is started +// startingHook is a hook that will be called before a container is started. func (c *DockerContainer) startingHook(ctx context.Context) error { - for _, lifecycleHooks := range c.lifecycleHooks { - err := containerHookFn(ctx, lifecycleHooks.PreStarts)(c) - if err != nil { - c.printLogs(ctx, err) - return err - } + errs := make([]error, len(c.lifecycleHooks)) + for i, lifecycleHooks := range c.lifecycleHooks { + errs[i] = containerHookFn(ctx, lifecycleHooks.PreStarts)(c) + } + + if err := errors.Join(errs...); err != nil { + c.printLogs(ctx, err) + return err } return nil } -// startedHook is a hook that will be called after a container is started +// startedHook is a hook that will be called after a container is started. func (c *DockerContainer) startedHook(ctx context.Context) error { - for _, lifecycleHooks := range c.lifecycleHooks { - err := containerHookFn(ctx, lifecycleHooks.PostStarts)(c) - if err != nil { - c.printLogs(ctx, err) - return err - } + errs := make([]error, len(c.lifecycleHooks)) + for i, lifecycleHooks := range c.lifecycleHooks { + errs[i] = containerHookFn(ctx, lifecycleHooks.PostStarts)(c) + } + + if err := errors.Join(errs...); err != nil { + c.printLogs(ctx, err) + return err } return nil } -// readiedHook is a hook that will be called after a container is ready +// readiedHook is a hook that will be called after a container is ready. func (c *DockerContainer) readiedHook(ctx context.Context) error { - for _, lifecycleHooks := range c.lifecycleHooks { - err := containerHookFn(ctx, lifecycleHooks.PostReadies)(c) - if err != nil { - c.printLogs(ctx, err) - return err - } + errs := make([]error, len(c.lifecycleHooks)) + for i, lifecycleHooks := range c.lifecycleHooks { + errs[i] = containerHookFn(ctx, lifecycleHooks.PostReadies)(c) + } + + if err := errors.Join(errs...); err != nil { + c.printLogs(ctx, err) + return err } return nil @@ -288,52 +291,44 @@ func (c *DockerContainer) printLogs(ctx context.Context, cause error) { c.logger.Printf("container logs (%s):\n%s", cause, b) } -// stoppingHook is a hook that will be called before a container is stopped +// stoppingHook is a hook that will be called before a container is stopped. func (c *DockerContainer) stoppingHook(ctx context.Context) error { - for _, lifecycleHooks := range c.lifecycleHooks { - err := containerHookFn(ctx, lifecycleHooks.PreStops)(c) - if err != nil { - return err - } + errs := make([]error, len(c.lifecycleHooks)) + for i, lifecycleHooks := range c.lifecycleHooks { + errs[i] = containerHookFn(ctx, lifecycleHooks.PreStops)(c) } - return nil + return errors.Join(errs...) } -// stoppedHook is a hook that will be called after a container is stopped +// stoppedHook is a hook that will be called after a container is stopped. func (c *DockerContainer) stoppedHook(ctx context.Context) error { - for _, lifecycleHooks := range c.lifecycleHooks { - err := containerHookFn(ctx, lifecycleHooks.PostStops)(c) - if err != nil { - return err - } + errs := make([]error, len(c.lifecycleHooks)) + for i, lifecycleHooks := range c.lifecycleHooks { + errs[i] = containerHookFn(ctx, lifecycleHooks.PostStops)(c) } - return nil + return errors.Join(errs...) } -// terminatingHook is a hook that will be called before a container is terminated +// terminatingHook is a hook that will be called before a container is terminated. func (c *DockerContainer) terminatingHook(ctx context.Context) error { - for _, lifecycleHooks := range c.lifecycleHooks { - err := containerHookFn(ctx, lifecycleHooks.PreTerminates)(c) - if err != nil { - return err - } + errs := make([]error, len(c.lifecycleHooks)) + for i, lifecycleHooks := range c.lifecycleHooks { + errs[i] = containerHookFn(ctx, lifecycleHooks.PreTerminates)(c) } - return nil + return errors.Join(errs...) } -// terminatedHook is a hook that will be called after a container is terminated +// terminatedHook is a hook that will be called after a container is terminated. func (c *DockerContainer) terminatedHook(ctx context.Context) error { - for _, lifecycleHooks := range c.lifecycleHooks { - err := containerHookFn(ctx, lifecycleHooks.PostTerminates)(c) - if err != nil { - return err - } + errs := make([]error, len(c.lifecycleHooks)) + for i, lifecycleHooks := range c.lifecycleHooks { + errs[i] = containerHookFn(ctx, lifecycleHooks.PostTerminates)(c) } - return nil + return errors.Join(errs...) } // Creating is a hook that will be called before a container is created.