|
|
@ -2,6 +2,8 @@ package container
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/docker/docker/api/types/container"
|
|
|
|
|
|
|
|
"github.com/docker/docker/api/types/filters"
|
|
|
|
"io/ioutil"
|
|
|
|
"io/ioutil"
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
@ -33,36 +35,48 @@ type Client interface {
|
|
|
|
// * DOCKER_HOST the docker-engine host to send api requests to
|
|
|
|
// * DOCKER_HOST the docker-engine host to send api requests to
|
|
|
|
// * DOCKER_TLS_VERIFY whether to verify tls certificates
|
|
|
|
// * DOCKER_TLS_VERIFY whether to verify tls certificates
|
|
|
|
// * DOCKER_API_VERSION the minimum docker api version to work with
|
|
|
|
// * DOCKER_API_VERSION the minimum docker api version to work with
|
|
|
|
func NewClient(pullImages bool) Client {
|
|
|
|
func NewClient(pullImages bool, includeStopped bool) Client {
|
|
|
|
cli, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv)
|
|
|
|
cli, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv)
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("Error instantiating Docker client: %s", err)
|
|
|
|
log.Fatalf("Error instantiating Docker client: %s", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return dockerClient{api: cli, pullImages: pullImages}
|
|
|
|
return dockerClient{
|
|
|
|
|
|
|
|
api: cli,
|
|
|
|
|
|
|
|
pullImages: pullImages,
|
|
|
|
|
|
|
|
includeStopped: includeStopped,
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
type dockerClient struct {
|
|
|
|
type dockerClient struct {
|
|
|
|
api dockerclient.CommonAPIClient
|
|
|
|
api dockerclient.CommonAPIClient
|
|
|
|
pullImages bool
|
|
|
|
pullImages bool
|
|
|
|
|
|
|
|
includeStopped bool
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (client dockerClient) ListContainers(fn Filter) ([]Container, error) {
|
|
|
|
func (client dockerClient) ListContainers(fn Filter) ([]Container, error) {
|
|
|
|
cs := []Container{}
|
|
|
|
cs := []Container{}
|
|
|
|
bg := context.Background()
|
|
|
|
bg := context.Background()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if client.includeStopped {
|
|
|
|
|
|
|
|
log.Debug("Retrieving containers including stopped and exited")
|
|
|
|
|
|
|
|
} else {
|
|
|
|
log.Debug("Retrieving running containers")
|
|
|
|
log.Debug("Retrieving running containers")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
runningContainers, err := client.api.ContainerList(
|
|
|
|
filter := client.createListFilter()
|
|
|
|
|
|
|
|
containers, err := client.api.ContainerList(
|
|
|
|
bg,
|
|
|
|
bg,
|
|
|
|
types.ContainerListOptions{})
|
|
|
|
types.ContainerListOptions{
|
|
|
|
|
|
|
|
Filters: filter,
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for _, runningContainer := range runningContainers {
|
|
|
|
for _, runningContainer := range containers {
|
|
|
|
containerInfo, err := client.api.ContainerInspect(bg, runningContainer.ID)
|
|
|
|
containerInfo, err := client.api.ContainerInspect(bg, runningContainer.ID)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
return nil, err
|
|
|
@ -83,6 +97,18 @@ func (client dockerClient) ListContainers(fn Filter) ([]Container, error) {
|
|
|
|
return cs, nil
|
|
|
|
return cs, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (client dockerClient) createListFilter() filters.Args {
|
|
|
|
|
|
|
|
filterArgs := filters.NewArgs()
|
|
|
|
|
|
|
|
filterArgs.Add("status", "running")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if client.includeStopped {
|
|
|
|
|
|
|
|
filterArgs.Add("status", "created")
|
|
|
|
|
|
|
|
filterArgs.Add("status", "exited")
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return filterArgs
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (client dockerClient) StopContainer(c Container, timeout time.Duration) error {
|
|
|
|
func (client dockerClient) StopContainer(c Container, timeout time.Duration) error {
|
|
|
|
bg := context.Background()
|
|
|
|
bg := context.Background()
|
|
|
|
signal := c.StopSignal()
|
|
|
|
signal := c.StopSignal()
|
|
|
@ -90,11 +116,12 @@ func (client dockerClient) StopContainer(c Container, timeout time.Duration) err
|
|
|
|
signal = defaultStopSignal
|
|
|
|
signal = defaultStopSignal
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if c.IsRunning() {
|
|
|
|
log.Infof("Stopping %s (%s) with %s", c.Name(), c.ID(), signal)
|
|
|
|
log.Infof("Stopping %s (%s) with %s", c.Name(), c.ID(), signal)
|
|
|
|
|
|
|
|
|
|
|
|
if err := client.api.ContainerKill(bg, c.ID(), signal); err != nil {
|
|
|
|
if err := client.api.ContainerKill(bg, c.ID(), signal); err != nil {
|
|
|
|
return err
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Wait for container to exit, but proceed anyway after the timeout elapses
|
|
|
|
// Wait for container to exit, but proceed anyway after the timeout elapses
|
|
|
|
client.waitForStop(c, timeout)
|
|
|
|
client.waitForStop(c, timeout)
|
|
|
@ -160,15 +187,23 @@ func (client dockerClient) StartContainer(c Container) error {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
log.Debugf("Starting container %s (%s)", name, creation.ID)
|
|
|
|
return client.startContainerIfPreviouslyRunning(bg, c, creation)
|
|
|
|
|
|
|
|
|
|
|
|
err = client.api.ContainerStart(bg, creation.ID, types.ContainerStartOptions{})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (client dockerClient) startContainerIfPreviouslyRunning(bg context.Context, c Container, creation container.ContainerCreateCreatedBody) error {
|
|
|
|
|
|
|
|
name := c.Name()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if !c.IsRunning() {
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log.Debugf("Starting container %s (%s)", name, creation.ID)
|
|
|
|
|
|
|
|
err := client.api.ContainerStart(bg, creation.ID, types.ContainerStartOptions{})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
return err
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (client dockerClient) RenameContainer(c Container, newName string) error {
|
|
|
|
func (client dockerClient) RenameContainer(c Container, newName string) error {
|
|
|
|