mirror of
https://github.com/drone/drone-cli.git
synced 2024-11-23 01:11:57 +01:00
refactored ambassador
This commit is contained in:
parent
8027800a30
commit
5c0bfedd01
@ -1,189 +0,0 @@
|
||||
package ambassador
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
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 {
|
||||
name string
|
||||
client dockerclient.Client
|
||||
}
|
||||
|
||||
// Create creates a new ambassador container.
|
||||
func Create(client dockerclient.Client) (_ *Ambassador, err error) {
|
||||
amb := &Ambassador{
|
||||
client: client,
|
||||
}
|
||||
|
||||
conf := &dockerclient.ContainerConfig{}
|
||||
host := &dockerclient.HostConfig{}
|
||||
conf.Entrypoint = []string{"/bin/sleep"}
|
||||
conf.Cmd = []string{"1d"}
|
||||
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 {
|
||||
|
||||
// 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("image", conf.Image).Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
err = client.StartContainer(amb.name, host)
|
||||
if err != nil {
|
||||
log.WithField("image", 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, "SIGKILL")
|
||||
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).Debugln("create container")
|
||||
|
||||
id, err := c.client.CreateContainer(conf, name)
|
||||
if err != nil {
|
||||
log.WithField("image", conf.Image).Errorln(err)
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
|
||||
// InspectContainer returns container details.
|
||||
func (c *Ambassador) InspectContainer(id string) (*dockerclient.ContainerInfo, error) {
|
||||
return c.client.InspectContainer(id)
|
||||
}
|
||||
|
||||
// ContainerLogs returns an io.ReadCloser for reading the
|
||||
// container logs.
|
||||
func (c *Ambassador) ContainerLogs(id string, options *dockerclient.LogOptions) (io.ReadCloser, error) {
|
||||
return c.client.ContainerLogs(id, options)
|
||||
}
|
||||
|
||||
// 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, "container:"+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
|
||||
}
|
||||
|
||||
// RemoveContainer removes a container.
|
||||
func (c *Ambassador) RemoveContainer(id string, force, volumes bool) error {
|
||||
return c.client.RemoveContainer(id, force, volumes)
|
||||
}
|
||||
|
||||
// KillContainer kills a running container.
|
||||
func (c *Ambassador) KillContainer(id, signal string) error {
|
||||
return c.client.KillContainer(id, signal)
|
||||
}
|
||||
|
||||
//
|
||||
// methods below are not implemented
|
||||
//
|
||||
|
||||
// Info returns a no-op error
|
||||
func (c *Ambassador) Info() (*dockerclient.Info, error) {
|
||||
return nil, errNop
|
||||
}
|
||||
|
||||
// ListContainers returns a no-op error
|
||||
func (c *Ambassador) ListContainers(all bool, size bool, filters string) ([]dockerclient.Container, error) {
|
||||
return nil, errNop
|
||||
}
|
||||
|
||||
// RestartContainer returns a no-op error
|
||||
func (c *Ambassador) RestartContainer(id string, timeout int) error {
|
||||
return errNop
|
||||
}
|
||||
|
||||
// StartMonitorEvents returns a no-op error
|
||||
func (c *Ambassador) StartMonitorEvents(cb dockerclient.Callback, ec chan error, args ...interface{}) {
|
||||
|
||||
}
|
||||
|
||||
// StopAllMonitorEvents returns a no-op error
|
||||
func (c *Ambassador) StopAllMonitorEvents() {
|
||||
|
||||
}
|
||||
|
||||
// Version returns a no-op error
|
||||
func (c *Ambassador) Version() (*dockerclient.Version, error) {
|
||||
return nil, errNop
|
||||
}
|
||||
|
||||
// ListImages returns a no-op error
|
||||
func (c *Ambassador) ListImages() ([]*dockerclient.Image, error) {
|
||||
return nil, errNop
|
||||
}
|
||||
|
||||
// RemoveImage returns a no-op error
|
||||
func (c *Ambassador) RemoveImage(name string) error {
|
||||
return errNop
|
||||
}
|
||||
|
||||
// PauseContainer returns a no-op error
|
||||
func (c *Ambassador) PauseContainer(name string) error {
|
||||
return errNop
|
||||
}
|
||||
|
||||
// UnpauseContainer returns a no-op error
|
||||
func (c *Ambassador) UnpauseContainer(name string) error {
|
||||
return errNop
|
||||
}
|
||||
|
||||
// Exec returns a no-op error
|
||||
func (c *Ambassador) Exec(config *dockerclient.ExecConfig) (string, error) {
|
||||
var empty string
|
||||
return empty, errNop
|
||||
}
|
106
builder/docker/ambassador.go
Normal file
106
builder/docker/ambassador.go
Normal file
@ -0,0 +1,106 @@
|
||||
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{"1d"}
|
||||
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 {
|
||||
|
||||
// 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("image", conf.Image).Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
err = client.StartContainer(amb.name, host)
|
||||
if err != nil {
|
||||
log.WithField("image", 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, "SIGKILL")
|
||||
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).Debugln("create container")
|
||||
|
||||
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, "container:"+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
|
||||
}
|
90
builder/worker/pool.go
Normal file
90
builder/worker/pool.go
Normal file
@ -0,0 +1,90 @@
|
||||
package worker
|
||||
|
||||
// import (
|
||||
// "sync"
|
||||
//
|
||||
// "github.com/drone/drone/server/worker"
|
||||
// "github.com/samalba/dockerclient"
|
||||
// )
|
||||
//
|
||||
// // TODO (bradrydzewski) ability to cancel work.
|
||||
// // TODO (bradrydzewski) ability to remove a worker.
|
||||
//
|
||||
// type Pool struct {
|
||||
// sync.Mutex
|
||||
// workers map[dockerclient.Client]bool
|
||||
// workerc chan dockerclient.Client
|
||||
// }
|
||||
//
|
||||
// func New() *Pool {
|
||||
// return &Pool{
|
||||
// workers: make(map[Worker]bool),
|
||||
// workerc: make(chan Worker, 999),
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Allocate allocates a worker to the pool to
|
||||
// // be available to accept work.
|
||||
// func (p *Pool) Allocate(w worker.Worker) bool {
|
||||
// if p.IsAllocated(w) {
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// p.Lock()
|
||||
// p.workers[w] = true
|
||||
// p.Unlock()
|
||||
//
|
||||
// p.workerc <- w
|
||||
// return true
|
||||
// }
|
||||
//
|
||||
// // IsAllocated is a helper function that returns
|
||||
// // true if the worker is currently allocated to
|
||||
// // the Pool.
|
||||
// func (p *Pool) IsAllocated(w worker.Worker) bool {
|
||||
// p.Lock()
|
||||
// defer p.Unlock()
|
||||
// _, ok := p.workers[w]
|
||||
// return ok
|
||||
// }
|
||||
//
|
||||
// // Deallocate removes the worker from the pool of
|
||||
// // available workers. If the worker is currently
|
||||
// // reserved and performing work it will finish,
|
||||
// // but no longer be given new work.
|
||||
// func (p *Pool) Deallocate(w worker.Worker) {
|
||||
// p.Lock()
|
||||
// defer p.Unlock()
|
||||
// delete(p.workers, w)
|
||||
// }
|
||||
//
|
||||
// // List returns a list of all Workers currently
|
||||
// // allocated to the Pool.
|
||||
// func (p *Pool) List() []worker.Worker {
|
||||
// p.Lock()
|
||||
// defer p.Unlock()
|
||||
//
|
||||
// var workers []worker.Worker
|
||||
// for w, _ := range p.workers {
|
||||
// workers = append(workers, w)
|
||||
// }
|
||||
// return workers
|
||||
// }
|
||||
//
|
||||
// // Reserve reserves the next available worker to
|
||||
// // start doing work. Once work is complete, the
|
||||
// // worker should be released back to the pool.
|
||||
// func (p *Pool) Reserve() <-chan worker.Worker {
|
||||
// return p.workerc
|
||||
// }
|
||||
//
|
||||
// // Release releases the worker back to the pool
|
||||
// // of available workers.
|
||||
// func (p *Pool) Release(w worker.Worker) bool {
|
||||
// if !p.IsAllocated(w) {
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// p.workerc <- w
|
||||
// return true
|
||||
// }
|
1
builder/worker/worker.go
Normal file
1
builder/worker/worker.go
Normal file
@ -0,0 +1 @@
|
||||
package worker
|
@ -4,10 +4,9 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/drone/drone-cli/builder"
|
||||
"github.com/drone/drone-cli/builder/ambassador"
|
||||
"github.com/drone/drone-cli/builder/docker"
|
||||
"github.com/drone/drone-cli/common"
|
||||
"github.com/drone/drone-cli/parser"
|
||||
"github.com/samalba/dockerclient"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
)
|
||||
@ -23,7 +22,7 @@ type Context struct {
|
||||
builder *builder.Builder
|
||||
config *common.Config
|
||||
|
||||
client dockerclient.Client
|
||||
client *docker.Ambassador
|
||||
}
|
||||
|
||||
func main() {
|
||||
@ -45,7 +44,7 @@ func main() {
|
||||
// list of builds and builders for each item
|
||||
// in the matrix
|
||||
for _, conf := range matrix {
|
||||
client, err := ambassador.Create(&mockClient{})
|
||||
client, err := docker.NewAmbassador(&mockClient{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user