2015-09-30 01:21:17 +00:00
|
|
|
package docker
|
|
|
|
|
|
|
|
import (
|
2016-02-12 18:17:30 +00:00
|
|
|
"errors"
|
2015-09-30 01:21:17 +00:00
|
|
|
|
2016-02-12 18:17:30 +00:00
|
|
|
log "github.com/Sirupsen/logrus"
|
2015-09-30 01:21:17 +00:00
|
|
|
"github.com/samalba/dockerclient"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
LogOpts = &dockerclient.LogOptions{
|
|
|
|
Stdout: true,
|
|
|
|
Stderr: true,
|
|
|
|
}
|
|
|
|
|
|
|
|
LogOptsTail = &dockerclient.LogOptions{
|
|
|
|
Follow: true,
|
|
|
|
Stdout: true,
|
|
|
|
Stderr: true,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
// Run creates the docker container, pulling images if necessary, starts
|
|
|
|
// the container and blocks until the container exits, returning the exit
|
|
|
|
// information.
|
|
|
|
func Run(client dockerclient.Client, conf *dockerclient.ContainerConfig, name string) (*dockerclient.ContainerInfo, error) {
|
|
|
|
info, err := RunDaemon(client, conf, name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return Wait(client, info.Id)
|
|
|
|
}
|
|
|
|
|
|
|
|
// RunDaemon creates the docker container, pulling images if necessary, starts
|
|
|
|
// the container and returns the container information. It does not wait for
|
|
|
|
// the container to exit.
|
|
|
|
func RunDaemon(client dockerclient.Client, conf *dockerclient.ContainerConfig, name string) (*dockerclient.ContainerInfo, error) {
|
|
|
|
|
2016-03-27 00:14:00 +00:00
|
|
|
// attempts to create the container
|
2016-03-07 19:23:49 +00:00
|
|
|
id, err := client.CreateContainer(conf, name, nil)
|
2015-09-30 01:21:17 +00:00
|
|
|
if err != nil {
|
|
|
|
// and pull the image and re-create if that fails
|
|
|
|
err = client.PullImage(conf.Image, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2016-03-07 19:23:49 +00:00
|
|
|
id, err = client.CreateContainer(conf, name, nil)
|
2015-09-30 01:21:17 +00:00
|
|
|
if err != nil {
|
|
|
|
client.RemoveContainer(id, true, true)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// fetches the container information
|
|
|
|
info, err := client.InspectContainer(id)
|
|
|
|
if err != nil {
|
|
|
|
client.RemoveContainer(id, true, true)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// starts the container
|
|
|
|
err = client.StartContainer(id, &conf.HostConfig)
|
|
|
|
if err != nil {
|
|
|
|
client.RemoveContainer(id, true, true)
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return info, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait blocks until the named container exits, returning the exit information.
|
|
|
|
func Wait(client dockerclient.Client, name string) (*dockerclient.ContainerInfo, error) {
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
client.StopContainer(name, 5)
|
|
|
|
client.KillContainer(name, "9")
|
|
|
|
}()
|
|
|
|
|
2016-02-12 18:54:16 +00:00
|
|
|
for attempts := 0; attempts < 5; attempts++ {
|
|
|
|
done := client.Wait(name)
|
|
|
|
<-done
|
2015-09-30 01:21:17 +00:00
|
|
|
|
2016-02-12 18:54:16 +00:00
|
|
|
info, err := client.InspectContainer(name)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
2015-09-30 01:21:17 +00:00
|
|
|
}
|
2016-02-12 18:17:30 +00:00
|
|
|
|
2016-02-12 18:54:16 +00:00
|
|
|
if !info.State.Running {
|
|
|
|
return info, nil
|
|
|
|
}
|
2015-09-30 01:21:17 +00:00
|
|
|
|
2016-02-12 18:54:16 +00:00
|
|
|
log.Debugf("attempting to resume waiting after %d attempts.\n", attempts)
|
2015-09-30 01:21:17 +00:00
|
|
|
}
|
2016-02-12 18:54:16 +00:00
|
|
|
|
|
|
|
return nil, errors.New("reached maximum wait attempts")
|
2015-09-30 01:21:17 +00:00
|
|
|
}
|