1
0
mirror of https://github.com/drone/drone-cli.git synced 2024-11-23 17:22:09 +01:00
drone-cli/builder/handler.go
2015-03-10 22:34:27 -07:00

116 lines
2.6 KiB
Go

package builder
import (
"io"
"github.com/drone/drone-cli/common"
"github.com/samalba/dockerclient"
)
// Handler defines an interface that can be implemented by objects
// that should be run during the build process. to run as part of a build.
type Handler interface {
Build(*ResultWriter) error
Cancel()
}
type handler struct {
name string
pull bool
detach bool
client dockerclient.Client
host *dockerclient.HostConfig
config *dockerclient.ContainerConfig
}
func (h *handler) Build(rw *ResultWriter) error {
name, err := h.client.CreateContainer(h.config, "")
if err != nil {
// on error try to pull the Docker image.
// note that this may not be the cause of
// the error, but we'll try just in case.
h.client.PullImage(h.config.Image, nil)
// then try to re-create
name, err = h.client.CreateContainer(h.config, "")
if err != nil {
return err
}
}
h.name = name
err = h.client.StartContainer(h.name, h.host)
if err != nil {
return err
}
// if we are running a service container we
// can just exit right here.
if h.detach {
return nil
}
// get the docker logs and write to the resposne.
logs := &dockerclient.LogOptions{
Follow: true,
Stderr: true,
Stdout: true,
Timestamps: true,
}
rc, err := h.client.ContainerLogs(h.name, logs)
if err != nil {
return err
}
io.Copy(rw, rc)
// get the container state and write the exit status
// to the response.
info, err := h.client.InspectContainer(h.name)
if err != nil {
return err
}
rw.WriteExitCode(info.State.ExitCode)
return nil
}
func (h *handler) Cancel() {
h.client.StopContainer(h.name, 5)
h.client.KillContainer(h.name, "SIGKILL")
h.client.RemoveContainer(h.name, true, false)
}
// Batch returns a handler that launches a container. The container
// will start and block until the container exits.
//
// The container output and result are written to the ResponseWriter.
func Batch(build *Build, step *common.Step) Handler {
host := toHostConfig(step)
conf := toContainerConfig(step)
if step.Config != nil {
conf.Cmd = toCommand(build, step)
conf.Entrypoint = []string{}
}
return &handler{
pull: step.Pull,
client: build.Client,
config: conf,
host: host,
}
}
// Service returns a handler that launches a service container as
// a daemon. The the container will start and then exit immediately,
// without blocking.
//
// The output and exit status will not be written to the ResponseWriter.
func Service(build *Build, step *common.Step) Handler {
host := toHostConfig(step)
conf := toContainerConfig(step)
return &handler{
pull: step.Pull,
client: build.Client,
detach: true,
config: conf,
host: host,
}
}