woodpecker/pkg/build/docker/container.go

146 lines
3.7 KiB
Go

package docker
import (
"fmt"
"io"
)
type ContainerService struct {
*Client
}
// List only running containers.
func (c *ContainerService) List() ([]*Containers, error) {
containers := []*Containers{}
err := c.do("GET", "/containers/json?all=0", nil, &containers)
return containers, err
}
// List all containers
func (c *ContainerService) ListAll() ([]*Containers, error) {
containers := []*Containers{}
err := c.do("GET", "/containers/json?all=1", nil, &containers)
return containers, err
}
// Create a Container
func (c *ContainerService) Create(conf *Config) (*Run, error) {
run, err := c.create(conf)
switch {
// if no error, exit immediately
case err == nil:
return run, nil
// if error we exit, unless it is
// a NOT FOUND error, which means we just
// need to download the Image from the center
// image index
case err != nil && err != ErrNotFound:
return nil, err
}
// attempt to pull the image
if err := c.Images.Pull(conf.Image); err != nil {
return nil, err
}
// now that we have the image, re-try creation
return c.create(conf)
}
func (c *ContainerService) create(conf *Config) (*Run, error) {
run := Run{}
err := c.do("POST", "/containers/create", conf, &run)
return &run, err
}
// Start the container id
func (c *ContainerService) Start(id string, conf *HostConfig) error {
return c.do("POST", fmt.Sprintf("/containers/%s/start", id), &conf, nil)
}
// Stop the container id
func (c *ContainerService) Stop(id string, timeout int) error {
return c.do("POST", fmt.Sprintf("/containers/%s/stop?t=%v", id, timeout), nil, nil)
}
// Remove the container id from the filesystem.
func (c *ContainerService) Remove(id string) error {
return c.do("DELETE", fmt.Sprintf("/containers/%s", id), nil, nil)
}
// Block until container id stops, then returns the exit code
func (c *ContainerService) Wait(id string) (*Wait, error) {
wait := Wait{}
err := c.do("POST", fmt.Sprintf("/containers/%s/wait", id), nil, &wait)
return &wait, err
}
// Attach to the container to stream the stdout and stderr
func (c *ContainerService) Attach(id string, out io.Writer) error {
path := fmt.Sprintf("/containers/%s/attach?&stream=1&stdout=1&stderr=1", id)
return c.hijack("POST", path, false, out)
}
// Stop the container id
func (c *ContainerService) Inspect(id string) (*Container, error) {
container := Container{}
err := c.do("GET", fmt.Sprintf("/containers/%s/json", id), nil, &container)
return &container, err
}
// Run the container
func (c *ContainerService) Run(conf *Config, host *HostConfig, out io.Writer) (*Wait, error) {
// create the container from the image
run, err := c.Create(conf)
if err != nil {
return nil, err
}
// attach to the container
go func() {
c.Attach(run.ID, out)
}()
// start the container
if err := c.Start(run.ID, host); err != nil {
return nil, err
}
// wait for the container to stop
wait, err := c.Wait(run.ID)
if err != nil {
return nil, err
}
return wait, nil
}
// Run the container as a Daemon
func (c *ContainerService) RunDaemon(conf *Config, host *HostConfig) (*Run, error) {
run, err := c.Create(conf)
if err != nil {
return nil, err
}
// start the container
err = c.Start(run.ID, host)
return run, err
}
func (c *ContainerService) RunDaemonPorts(image string, ports map[Port]struct{}) (*Run, error) {
// setup configuration
config := Config{Image: image}
config.ExposedPorts = ports
// host configuration
host := HostConfig{}
host.PortBindings = make(map[Port][]PortBinding)
// loop through and add ports
for port, _ := range ports {
host.PortBindings[port] = []PortBinding{{HostIp: "127.0.0.1", HostPort: ""}}
}
//127.0.0.1::%s
//map[3306/tcp:{}] map[3306/tcp:[{127.0.0.1 }]]
return c.RunDaemon(&config, &host)
}