110 lines
3.1 KiB
Go
110 lines
3.1 KiB
Go
package docker
|
|
|
|
import (
|
|
"errors"
|
|
|
|
log "github.com/Sirupsen/logrus"
|
|
"github.com/samalba/dockerclient"
|
|
)
|
|
|
|
var errNop = errors.New("Operation not supported")
|
|
|
|
// Ambassador is a wrapper around the Docker client that
|
|
// provides a shared volume and network for all containers.
|
|
type Ambassador struct {
|
|
dockerclient.Client
|
|
name string
|
|
}
|
|
|
|
// NewAmbassador creates an ambassador container and wraps the Docker
|
|
// client to inject the ambassador volume and network into containers.
|
|
func NewAmbassador(client dockerclient.Client) (_ *Ambassador, err error) {
|
|
amb := &Ambassador{client, ""}
|
|
|
|
conf := &dockerclient.ContainerConfig{}
|
|
host := &dockerclient.HostConfig{}
|
|
conf.Entrypoint = []string{"/bin/sleep"}
|
|
conf.Cmd = []string{"86400"}
|
|
conf.Image = "busybox"
|
|
conf.Volumes = map[string]struct{}{}
|
|
conf.Volumes["/drone"] = struct{}{}
|
|
|
|
// creates the ambassador container
|
|
amb.name, err = client.CreateContainer(conf, "")
|
|
if err != nil {
|
|
log.WithField("ambassador", conf.Image).Errorln(err)
|
|
|
|
// on failure attempts to pull the image
|
|
client.PullImage(conf.Image, nil)
|
|
|
|
// then attempts to re-create the container
|
|
amb.name, err = client.CreateContainer(conf, "")
|
|
if err != nil {
|
|
log.WithField("ambassador", conf.Image).Errorln(err)
|
|
return nil, err
|
|
}
|
|
}
|
|
err = client.StartContainer(amb.name, host)
|
|
if err != nil {
|
|
log.WithField("ambassador", conf.Image).Errorln(err)
|
|
}
|
|
return amb, err
|
|
}
|
|
|
|
// Destroy stops and deletes the ambassador container.
|
|
func (c *Ambassador) Destroy() error {
|
|
c.Client.StopContainer(c.name, 5)
|
|
c.Client.KillContainer(c.name, "9")
|
|
return c.Client.RemoveContainer(c.name, true, true)
|
|
}
|
|
|
|
// CreateContainer creates a container.
|
|
func (c *Ambassador) CreateContainer(conf *dockerclient.ContainerConfig, name string) (string, error) {
|
|
log.WithField("image", conf.Image).Infoln("create container")
|
|
|
|
// add the affinity flag for swarm
|
|
conf.Env = append(conf.Env, "affinity:container=="+c.name)
|
|
|
|
id, err := c.Client.CreateContainer(conf, name)
|
|
if err != nil {
|
|
log.WithField("image", conf.Image).Errorln(err)
|
|
}
|
|
return id, err
|
|
}
|
|
|
|
// StartContainer starts a container. The ambassador volume
|
|
// is automatically linked. The ambassador network is linked
|
|
// iff a network mode is not already specified.
|
|
func (c *Ambassador) StartContainer(id string, conf *dockerclient.HostConfig) error {
|
|
log.WithField("container", id).Debugln("start container")
|
|
|
|
conf.VolumesFrom = append(conf.VolumesFrom, c.name)
|
|
if len(conf.NetworkMode) == 0 {
|
|
conf.NetworkMode = "container:" + c.name
|
|
}
|
|
err := c.Client.StartContainer(id, conf)
|
|
if err != nil {
|
|
log.WithField("container", id).Errorln(err)
|
|
}
|
|
return err
|
|
}
|
|
|
|
// StopContainer stops a container.
|
|
func (c *Ambassador) StopContainer(id string, timeout int) error {
|
|
log.WithField("container", id).Debugln("stop container")
|
|
err := c.Client.StopContainer(id, timeout)
|
|
if err != nil {
|
|
log.WithField("container", id).Errorln(err)
|
|
}
|
|
return err
|
|
}
|
|
|
|
// PullImage pulls an image.
|
|
func (c *Ambassador) PullImage(name string, auth *dockerclient.AuthConfig) error {
|
|
log.WithField("image", name).Debugln("pull image")
|
|
err := c.Client.PullImage(name, auth)
|
|
if err != nil {
|
|
log.WithField("image", name).Errorln(err)
|
|
}
|
|
return err
|
|
}
|