api/v1beta1: use go-dockerclient instead of docker-api-structs

This involves updating go-dockerclient and removing the patched code.

Related to #692 and fsouza/go-dockerclient#146.
pull/6/head
Francisco Souza 2014-09-05 17:31:13 -03:00
parent ee1c0838d8
commit 6d0f84c700
17 changed files with 389 additions and 273 deletions

4
Godeps/Godeps.json generated
View File

@ -47,8 +47,8 @@
},
{
"ImportPath": "github.com/fsouza/go-dockerclient",
"Comment": "0.2.1-216-g9061c85",
"Rev": "9061c8580ba4374f24de44bcf9e8b77ce0553933"
"Comment": "0.2.1-241-g0dbb508",
"Rev": "0dbb508e94dd899a6743d035d8f249c7634d26da"
},
{
"ImportPath": "github.com/golang/glog",

View File

@ -2,7 +2,7 @@ language: go
go:
- 1.1.2
- 1.2
- 1.3
- 1.3.1
- tip
env:
- GOARCH=amd64

View File

@ -1,5 +1,6 @@
# This is the official list of go-dockerclient authors for copyright purposes.
Aldrin Leal <aldrin@leal.eng.br>
Andreas Jaekle <andreas@jaekle.net>
Andrews Medina <andrewsmedina@gmail.com>
Andy Goldstein <andy.goldstein@redhat.com>
@ -7,6 +8,8 @@ Ben McCann <benmccann.com>
Cezar Sa Espinola <cezar.sa@corp.globo.com>
Cheah Chu Yeow <chuyeow@gmail.com>
cheneydeng <cheneydeng@qq.com>
Daniel, Dao Quang Minh <dqminh89@gmail.com>
David Huie <dahuie@gmail.com>
Ed <edrocksit@gmail.com>
Eric Anderson <anderson@copperegg.com>
Fabio Rehm <fgrehm@gmail.com>
@ -19,6 +22,7 @@ Jeff Mitchell <jeffrey.mitchell@gmail.com>
Jeffrey Hulten <jhulten@gmail.com>
Johan Euphrosine <proppy@google.com>
Karan Misra <kidoman@gmail.com>
Kim, Hirokuni <hirokuni.kim@kvh.co.jp>
Lucas Clemente <lucas@clemente.io>
Omeid Matten <public@omeid.me>
Paul Morie <pmorie@gmail.com>

View File

@ -264,7 +264,7 @@ func (c *Client) do(method, path string, data interface{}) ([]byte, int, error)
return body, resp.StatusCode, nil
}
func (c *Client) stream(method, path string, setRawTerminal bool, headers map[string]string, in io.Reader, stdout, stderr io.Writer) error {
func (c *Client) stream(method, path string, setRawTerminal, rawJSONStream bool, headers map[string]string, in io.Reader, stdout, stderr io.Writer) error {
if (method == "POST" || method == "PUT") && in == nil {
in = bytes.NewReader(nil)
}
@ -320,6 +320,12 @@ func (c *Client) stream(method, path string, setRawTerminal bool, headers map[st
return newError(resp.StatusCode, body)
}
if resp.Header.Get("Content-Type") == "application/json" {
// if we want to get raw json stream, just copy it back to output
// without decoding it
if rawJSONStream {
_, err = io.Copy(stdout, resp.Body)
return err
}
dec := json.NewDecoder(resp.Body)
for {
var m jsonMessage

View File

@ -248,16 +248,22 @@ func TestPingFailingWrongStatus(t *testing.T) {
type FakeRoundTripper struct {
message string
status int
header map[string]string
requests []*http.Request
}
func (rt *FakeRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
body := strings.NewReader(rt.message)
rt.requests = append(rt.requests, r)
return &http.Response{
res := &http.Response{
StatusCode: rt.status,
Body: ioutil.NopCloser(body),
}, nil
Header: make(http.Header),
}
for k, v := range rt.header {
res.Header.Set(k, v)
}
return res, nil
}
func (rt *FakeRoundTripper) Reset() {

View File

@ -28,25 +28,25 @@ type ListContainersOptions struct {
}
type APIPort struct {
PrivatePort int64
PublicPort int64
Type string
IP string
PrivatePort int64 `json:"PrivatePort,omitempty" yaml:"PrivatePort,omitempty"`
PublicPort int64 `json:"PublicPort,omitempty" yaml:"PublicPort,omitempty"`
Type string `json:"Type,omitempty" yaml:"Type,omitempty"`
IP string `json:"IP,omitempty" yaml:"IP,omitempty"`
}
// APIContainers represents a container.
//
// See http://goo.gl/QeFH7U for more details.
type APIContainers struct {
ID string `json:"Id"`
Image string
Command string
Created int64
Status string
Ports []APIPort
SizeRw int64
SizeRootFs int64
Names []string
ID string `json:"Id" yaml:"Id"`
Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
Command string `json:"Command,omitempty" yaml:"Command,omitempty"`
Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"`
Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
Ports []APIPort `json:"Ports,omitempty" yaml:"Ports,omitempty"`
SizeRw int64 `json:"SizeRw,omitempty" yaml:"SizeRw,omitempty"`
SizeRootFs int64 `json:"SizeRootFs,omitempty" yaml:"SizeRootFs,omitempty"`
Names []string `json:"Names,omitempty" yaml:"Names,omitempty"`
}
// ListContainers returns a slice of containers matching the given criteria.
@ -86,12 +86,12 @@ func (p Port) Proto() string {
// State represents the state of a container.
type State struct {
Running bool
Paused bool
Pid int
ExitCode int
StartedAt time.Time
FinishedAt time.Time
Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"`
Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"`
ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
StartedAt time.Time `json:"StartedAt,omitempty" yaml:"StartedAt,omitempty"`
FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"`
}
// String returns the string representation of a state.
@ -106,19 +106,19 @@ func (s *State) String() string {
}
type PortBinding struct {
HostIp string
HostPort string
HostIp string `json:"HostIP,omitempty" yaml:"HostIP,omitempty"`
HostPort string `json:"HostPort,omitempty" yaml:"HostPort,omitempty"`
}
type PortMapping map[string]string
type NetworkSettings struct {
IPAddress string
IPPrefixLen int
Gateway string
Bridge string
PortMapping map[string]PortMapping
Ports map[Port][]PortBinding
IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty"`
Gateway string `json:"Gateway,omitempty" yaml:"Gateway,omitempty"`
Bridge string `json:"Bridge,omitempty" yaml:"Bridge,omitempty"`
PortMapping map[string]PortMapping `json:"PortMapping,omitempty" yaml:"PortMapping,omitempty"`
Ports map[Port][]PortBinding `json:"Ports,omitempty" yaml:"Ports,omitempty"`
}
func (settings *NetworkSettings) PortMappingAPI() []APIPort {
@ -155,55 +155,55 @@ func parsePort(rawPort string) (int, error) {
}
type Config struct {
Hostname string
Domainname string
User string
Memory int64
MemorySwap int64
CpuShares int64
AttachStdin bool
AttachStdout bool
AttachStderr bool
PortSpecs []string
ExposedPorts map[Port]struct{}
Tty bool
OpenStdin bool
StdinOnce bool
Env []string
Cmd []string
Dns []string // For Docker API v1.9 and below only
Image string
Volumes map[string]struct{}
VolumesFrom string
WorkingDir string
Entrypoint []string
NetworkDisabled bool
Hostname string `json:"Hostname,omitempty" yaml:"Hostname,omitempty"`
Domainname string `json:"Domainname,omitempty" yaml:"Domainname,omitempty"`
User string `json:"User,omitempty" yaml:"User,omitempty"`
Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty"`
CpuShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty"`
AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty"`
AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty"`
AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty"`
PortSpecs []string `json:"PortSpecs,omitempty" yaml:"PortSpecs,omitempty"`
ExposedPorts map[Port]struct{} `json:"ExposedPorts,omitempty" yaml:"ExposedPorts,omitempty"`
Tty bool `json:"Tty,omitempty" yaml:"Tty,omitempty"`
OpenStdin bool `json:"OpenStdin,omitempty" yaml:"OpenStdin,omitempty"`
StdinOnce bool `json:"StdinOnce,omitempty" yaml:"StdinOnce,omitempty"`
Env []string `json:"Env,omitempty" yaml:"Env,omitempty"`
Cmd []string `json:"Cmd,omitempty" yaml:"Cmd,omitempty"`
Dns []string `json:"Dns,omitempty" yaml:"Dns,omitempty"` // For Docker API v1.9 and below only
Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
Volumes map[string]struct{} `json:"Volumes,omitempty" yaml:"Volumes,omitempty"`
VolumesFrom string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
WorkingDir string `json:"WorkingDir,omitempty" yaml:"WorkingDir,omitempty"`
Entrypoint []string `json:"Entrypoint,omitempty" yaml:"Entrypoint,omitempty"`
NetworkDisabled bool `json:"NetworkDisabled,omitempty" yaml:"NetworkDisabled,omitempty"`
}
type Container struct {
ID string
ID string `json:"Id" yaml:"Id"`
Created time.Time
Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
Path string
Args []string
Path string `json:"Path,omitempty" yaml:"Path,omitempty"`
Args []string `json:"Args,omitempty" yaml:"Args,omitempty"`
Config *Config
State State
Image string
Config *Config `json:"Config,omitempty" yaml:"Config,omitempty"`
State State `json:"State,omitempty" yaml:"State,omitempty"`
Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
NetworkSettings *NetworkSettings
NetworkSettings *NetworkSettings `json:"NetworkSettings,omitempty" yaml:"NetworkSettings,omitempty"`
SysInitPath string
ResolvConfPath string
HostnamePath string
HostsPath string
Name string
Driver string
SysInitPath string `json:"SysInitPath,omitempty" yaml:"SysInitPath,omitempty"`
ResolvConfPath string `json:"ResolvConfPath,omitempty" yaml:"ResolvConfPath,omitempty"`
HostnamePath string `json:"HostnamePath,omitempty" yaml:"HostnamePath,omitempty"`
HostsPath string `json:"HostsPath,omitempty" yaml:"HostsPath,omitempty"`
Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
Driver string `json:"Driver,omitempty" yaml:"Driver,omitempty"`
Volumes map[string]string
VolumesRW map[string]bool
HostConfig *HostConfig
Volumes map[string]string `json:"Volumes,omitempty" yaml:"Volumes,omitempty"`
VolumesRW map[string]bool `json:"VolumesRW,omitempty" yaml:"VolumesRW,omitempty"`
HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"`
}
// InspectContainer returns information about a container by its ID.
@ -279,22 +279,56 @@ func (c *Client) CreateContainer(opts CreateContainerOptions) (*Container, error
}
type KeyValuePair struct {
Key string
Value string
Key string `json:"Key,omitempty" yaml:"Key,omitempty"`
Value string `json:"Value,omitempty" yaml:"Value,omitempty"`
}
// RestartPolicy represents the policy for automatically restarting a container.
//
// Possible values are:
//
// - always: the docker daemon will always restart the container
// - on-failure: the docker daemon will restart the container on failures, at
// most MaximumRetryCount times
// - no: the docker daemon will not restart the container automatically
type RestartPolicy struct {
Name string `json:"Name,omitempty" yaml:"Name,omitempty"`
MaximumRetryCount int `json:"MaximumRetryCount,omitempty" yaml:"MaximumRetryCount,omitempty"`
}
// AlwaysRestart returns a restart policy that tells the Docker daemon to
// always restart the container.
func AlwaysRestart() RestartPolicy {
return RestartPolicy{Name: "always"}
}
// RestartOnFailure returns a restart policy that tells the Docker daemon to
// restart the container on failures, trying at most maxRetry times.
func RestartOnFailure(maxRetry int) RestartPolicy {
return RestartPolicy{Name: "on-failure", MaximumRetryCount: maxRetry}
}
// NeverRestart returns a restart policy that tells the Docker daemon to never
// restart the container on failures.
func NeverRestart() RestartPolicy {
return RestartPolicy{Name: "no"}
}
type HostConfig struct {
Binds []string
ContainerIDFile string
LxcConf []KeyValuePair
Privileged bool
PortBindings map[Port][]PortBinding
Links []string
PublishAllPorts bool
Dns []string // For Docker API v1.10 and above only
DnsSearch []string
VolumesFrom []string
NetworkMode string
Binds []string `json:"Binds,omitempty" yaml:"Binds,omitempty"`
CapAdd []string `json:"CapAdd,omitempty" yaml:"CapAdd,omitempty"`
CapDrop []string `json:"CapDrop,omitempty" yaml:"CapDrop,omitempty"`
ContainerIDFile string `json:"ContainerIDFile,omitempty" yaml:"ContainerIDFile,omitempty"`
LxcConf []KeyValuePair `json:"LxcConf,omitempty" yaml:"LxcConf,omitempty"`
Privileged bool `json:"Privileged,omitempty" yaml:"Privileged,omitempty"`
PortBindings map[Port][]PortBinding `json:"PortBindings,omitempty" yaml:"PortBindings,omitempty"`
Links []string `json:"Links,omitempty" yaml:"Links,omitempty"`
PublishAllPorts bool `json:"PublishAllPorts,omitempty" yaml:"PublishAllPorts,omitempty"`
Dns []string `json:"Dns,omitempty" yaml:"Dns,omitempty"` // For Docker API v1.10 and above only
DnsSearch []string `json:"DnsSearch,omitempty" yaml:"DnsSearch,omitempty"`
VolumesFrom []string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
NetworkMode string `json:"NetworkMode,omitempty" yaml:"NetworkMode,omitempty"`
RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty"`
}
// StartContainer starts a container, returning an error in case of failure.
@ -309,6 +343,9 @@ func (c *Client) StartContainer(id string, hostConfig *HostConfig) error {
if status == http.StatusNotFound {
return &NoSuchContainer{ID: id}
}
if status == http.StatusNotModified {
return &ContainerAlreadyRunning{ID: id}
}
if err != nil {
return err
}
@ -325,6 +362,9 @@ func (c *Client) StopContainer(id string, timeout uint) error {
if status == http.StatusNotFound {
return &NoSuchContainer{ID: id}
}
if status == http.StatusNotModified {
return &ContainerNotRunning{ID: id}
}
if err != nil {
return err
}
@ -590,7 +630,7 @@ func (c *Client) Logs(opts LogsOptions) error {
opts.Tail = "all"
}
path := "/containers/" + opts.Container + "/logs?" + queryString(opts)
return c.stream("GET", path, opts.RawTerminal, nil, nil, opts.OutputStream, opts.ErrorStream)
return c.stream("GET", path, opts.RawTerminal, false, nil, nil, opts.OutputStream, opts.ErrorStream)
}
// ResizeContainerTTY resizes the terminal to the given height and width.
@ -617,10 +657,10 @@ type ExportContainerOptions struct {
// See http://goo.gl/Lqk0FZ for more details.
func (c *Client) ExportContainer(opts ExportContainerOptions) error {
if opts.ID == "" {
return NoSuchContainer{ID: opts.ID}
return &NoSuchContainer{ID: opts.ID}
}
url := fmt.Sprintf("/containers/%s/export", opts.ID)
return c.stream("GET", url, true, nil, nil, opts.OutputStream, nil)
return c.stream("GET", url, true, false, nil, nil, opts.OutputStream, nil)
}
// NoSuchContainer is the error returned when a given container does not exist.
@ -628,6 +668,26 @@ type NoSuchContainer struct {
ID string
}
func (err NoSuchContainer) Error() string {
func (err *NoSuchContainer) Error() string {
return "No such container: " + err.ID
}
// ContainerAlreadyRunning is the error returned when a given container is
// already running.
type ContainerAlreadyRunning struct {
ID string
}
func (err *ContainerAlreadyRunning) Error() string {
return "Container already running: " + err.ID
}
// ContainerNotRunning is the error returned when a given container is not
// running.
type ContainerNotRunning struct {
ID string
}
func (err *ContainerNotRunning) Error() string {
return "Container not running: " + err.ID
}

View File

@ -493,6 +493,15 @@ func TestStartContainerNotFound(t *testing.T) {
}
}
func TestStartContainerAlreadyRunning(t *testing.T) {
client := newTestClient(&FakeRoundTripper{message: "container already running", status: http.StatusNotModified})
err := client.StartContainer("a2334", &HostConfig{})
expected := &ContainerAlreadyRunning{ID: "a2334"}
if !reflect.DeepEqual(err, expected) {
t.Errorf("StartContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
}
}
func TestStopContainer(t *testing.T) {
fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
client := newTestClient(fakeRT)
@ -520,6 +529,15 @@ func TestStopContainerNotFound(t *testing.T) {
}
}
func TestStopContainerNotRunning(t *testing.T) {
client := newTestClient(&FakeRoundTripper{message: "container not running", status: http.StatusNotModified})
err := client.StopContainer("a2334", 10)
expected := &ContainerNotRunning{ID: "a2334"}
if !reflect.DeepEqual(err, expected) {
t.Errorf("StopContainer: Wrong error returned. Want %#v. Got %#v.", expected, err)
}
}
func TestRestartContainer(t *testing.T) {
fakeRT := &FakeRoundTripper{message: "", status: http.StatusNoContent}
client := newTestClient(fakeRT)
@ -1313,8 +1331,12 @@ func TestExportContainerNoId(t *testing.T) {
client := Client{}
out := stdoutMock{bytes.NewBufferString("")}
err := client.ExportContainer(ExportContainerOptions{OutputStream: out})
if err != (NoSuchContainer{}) {
t.Errorf("ExportContainer: wrong error. Want %#v. Got %#v.", NoSuchContainer{}, err)
e, ok := err.(*NoSuchContainer)
if !ok {
t.Errorf("ExportContainer: wrong error. Want NoSuchContainer. Got %#v.", e)
}
if e.ID != "" {
t.Errorf("ExportContainer: wrong ID. Want %q. Got %q", "", e.ID)
}
}
@ -1361,3 +1383,34 @@ func TestPassingNameOptToCreateContainerReturnsItInContainer(t *testing.T) {
t.Errorf("Container name expected to be TestCreateContainer, was %s", container.Name)
}
}
func TestAlwaysRestart(t *testing.T) {
policy := AlwaysRestart()
if policy.Name != "always" {
t.Errorf("AlwaysRestart(): wrong policy name. Want %q. Got %q", "always", policy.Name)
}
if policy.MaximumRetryCount != 0 {
t.Errorf("AlwaysRestart(): wrong MaximumRetryCount. Want 0. Got %d", policy.MaximumRetryCount)
}
}
func TestRestartOnFailure(t *testing.T) {
const retry = 5
policy := RestartOnFailure(retry)
if policy.Name != "on-failure" {
t.Errorf("RestartOnFailure(%d): wrong policy name. Want %q. Got %q", retry, "on-failure", policy.Name)
}
if policy.MaximumRetryCount != retry {
t.Errorf("RestartOnFailure(%d): wrong MaximumRetryCount. Want %d. Got %d", retry, retry, policy.MaximumRetryCount)
}
}
func TestNeverRestart(t *testing.T) {
policy := NeverRestart()
if policy.Name != "no" {
t.Errorf("NeverRestart(): wrong policy name. Want %q. Got %q", "always", policy.Name)
}
if policy.MaximumRetryCount != 0 {
t.Errorf("NeverRestart(): wrong MaximumRetryCount. Want 0. Got %d", policy.MaximumRetryCount)
}
}

View File

@ -20,10 +20,10 @@ import (
// APIEvents represents an event returned by the API.
type APIEvents struct {
Status string
ID string
From string
Time int64
Status string `json:"Status,omitempty" yaml:"Status,omitempty"`
ID string `json:"ID,omitempty" yaml:"ID,omitempty"`
From string `json:"From,omitempty" yaml:"From,omitempty"`
Time int64 `json:"Time,omitempty" yaml:"Time,omitempty"`
}
type eventMonitoringState struct {

View File

@ -8,10 +8,11 @@ import (
"archive/tar"
"bytes"
"fmt"
"github.com/fsouza/go-dockerclient"
"io"
"log"
"time"
"github.com/fsouza/go-dockerclient"
)
func ExampleClient_AttachToContainer() {

View File

@ -20,28 +20,26 @@ import (
// APIImages represent an image returned in the ListImages call.
type APIImages struct {
ID string `json:"Id"`
RepoTags []string `json:",omitempty"`
Created int64
Size int64
VirtualSize int64
ParentId string `json:",omitempty"`
Repository string `json:",omitempty"`
Tag string `json:",omitempty"`
ID string `json:"Id" yaml:"Id"`
RepoTags []string `json:"RepoTags,omitempty" yaml:"RepoTags,omitempty"`
Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"`
Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
VirtualSize int64 `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
ParentId string `json:"ParentId,omitempty" yaml:"ParentId,omitempty"`
}
type Image struct {
ID string `json:"id"`
Parent string `json:"parent,omitempty"`
Comment string `json:"comment,omitempty"`
Created time.Time `json:"created"`
Container string `json:"container,omitempty"`
ContainerConfig Config `json:"containerconfig,omitempty"`
DockerVersion string `json:"dockerversion,omitempty"`
Author string `json:"author,omitempty"`
Config *Config `json:"config,omitempty"`
Architecture string `json:"architecture,omitempty"`
Size int64
ID string `json:"Id" yaml:"Id"`
Parent string `json:"Parent,omitempty" yaml:"Parent,omitempty"`
Comment string `json:"Comment,omitempty" yaml:"Comment,omitempty"`
Created time.Time `json:"Created,omitempty" yaml:"Created,omitempty"`
Container string `json:"Container,omitempty" yaml:"Container,omitempty"`
ContainerConfig Config `json:"ContainerConfig,omitempty" yaml:"ContainerConfig,omitempty"`
DockerVersion string `json:"DockerVersion,omitempty" yaml:"DockerVersion,omitempty"`
Author string `json:"Author,omitempty" yaml:"Author,omitempty"`
Config *Config `json:"Config,omitempty" yaml:"Config,omitempty"`
Architecture string `json:"Architecture,omitempty" yaml:"Architecture,omitempty"`
Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
}
type ImagePre012 struct {
@ -55,7 +53,7 @@ type ImagePre012 struct {
Author string `json:"author,omitempty"`
Config *Config `json:"config,omitempty"`
Architecture string `json:"architecture,omitempty"`
Size int64
Size int64 `json:"size,omitempty"`
}
var (
@ -164,7 +162,7 @@ type PushImageOptions struct {
}
// AuthConfiguration represents authentication options to use in the PushImage
// method. It represents the authencation in the Docker index server.
// method. It represents the authentication in the Docker index server.
type AuthConfiguration struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
@ -190,7 +188,7 @@ func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error
headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())
return c.stream("POST", path, true, headers, nil, opts.OutputStream, nil)
return c.stream("POST", path, true, false, headers, nil, opts.OutputStream, nil)
}
// PullImageOptions present the set of options available for pulling an image
@ -198,10 +196,11 @@ func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error
//
// See http://goo.gl/PhBKnS for more details.
type PullImageOptions struct {
Repository string `qs:"fromImage"`
Registry string
Tag string
OutputStream io.Writer `qs:"-"`
Repository string `qs:"fromImage"`
Registry string
Tag string
OutputStream io.Writer `qs:"-"`
RawJSONStream bool `qs:"-"`
}
// PullImage pulls an image from a remote registry, logging progress to w.
@ -217,12 +216,41 @@ func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error
json.NewEncoder(&buf).Encode(auth)
headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())
return c.createImage(queryString(&opts), headers, nil, opts.OutputStream)
return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream)
}
func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer) error {
func (c *Client) createImage(qs string, headers map[string]string, in io.Reader, w io.Writer, rawJSONStream bool) error {
path := "/images/create?" + qs
return c.stream("POST", path, true, headers, in, w, nil)
return c.stream("POST", path, true, rawJSONStream, headers, in, w, nil)
}
// LoadImageOptions represents the options for LoadImage Docker API Call
//
// See http://goo.gl/Y8NNCq for more details.
type LoadImageOptions struct {
InputStream io.Reader
}
// LoadImage imports a tarball docker image
//
// See http://goo.gl/Y8NNCq for more details.
func (c *Client) LoadImage(opts LoadImageOptions) error {
return c.stream("POST", "/images/load", true, false, nil, opts.InputStream, nil, nil)
}
// ExportImageOptions represent the options for ExportImage Docker API call
//
// See http://goo.gl/mi6kvk for more details.
type ExportImageOptions struct {
Name string
OutputStream io.Writer
}
// ExportImage exports an image (as a tar file) into the stream
//
// See http://goo.gl/mi6kvk for more details.
func (c *Client) ExportImage(opts ExportImageOptions) error {
return c.stream("GET", fmt.Sprintf("/images/%s/get", opts.Name), true, false, nil, nil, opts.OutputStream, nil)
}
// ImportImageOptions present the set of informations available for importing
@ -257,20 +285,21 @@ func (c *Client) ImportImage(opts ImportImageOptions) error {
opts.InputStream = bytes.NewBuffer(b)
opts.Source = "-"
}
return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream)
return c.createImage(queryString(&opts), nil, opts.InputStream, opts.OutputStream, false)
}
// BuildImageOptions present the set of informations available for building
// an image from a tarfile with a Dockerfile in it,the details about Dockerfile
// see http://docs.docker.io/en/latest/reference/builder/
type BuildImageOptions struct {
Name string `qs:"t"`
NoCache bool `qs:"nocache"`
SuppressOutput bool `qs:"q"`
RmTmpContainer bool `qs:"rm"`
InputStream io.Reader `qs:"-"`
OutputStream io.Writer `qs:"-"`
Remote string `qs:"remote"`
Name string `qs:"t"`
NoCache bool `qs:"nocache"`
SuppressOutput bool `qs:"q"`
RmTmpContainer bool `qs:"rm"`
ForceRmTmpContainer bool `qs:"forcerm"`
InputStream io.Reader `qs:"-"`
OutputStream io.Writer `qs:"-"`
Remote string `qs:"remote"`
}
// BuildImage builds an image from a tarball's url or a Dockerfile in the input
@ -289,7 +318,7 @@ func (c *Client) BuildImage(opts BuildImageOptions) error {
return ErrMissingRepo
}
return c.stream("POST", fmt.Sprintf("/build?%s",
queryString(&opts)), true, headers, opts.InputStream, opts.OutputStream, nil)
queryString(&opts)), true, false, headers, opts.InputStream, opts.OutputStream, nil)
}
// TagImageOptions present the set of options to tag an image

View File

@ -309,6 +309,33 @@ func TestPullImage(t *testing.T) {
}
}
func TestPullImageWithRawJSON(t *testing.T) {
body := `
{"status":"Pulling..."}
{"status":"Pulling", "progress":"1 B/ 100 B", "progressDetail":{"current":1, "total":100}}
`
fakeRT := &FakeRoundTripper{
message: body,
status: http.StatusOK,
header: map[string]string{
"Content-Type": "application/json",
},
}
client := newTestClient(fakeRT)
var buf bytes.Buffer
err := client.PullImage(PullImageOptions{
Repository: "base",
OutputStream: &buf,
RawJSONStream: true,
}, AuthConfiguration{})
if err != nil {
t.Fatal(err)
}
if buf.String() != body {
t.Errorf("PullImage: Wrong raw output. Want %q. Got %q", body, buf.String())
}
}
func TestPullImageWithoutOutputStream(t *testing.T) {
fakeRT := &FakeRoundTripper{message: "Pulling 1/100", status: http.StatusOK}
client := newTestClient(fakeRT)
@ -514,19 +541,20 @@ func TestBuildImageParameters(t *testing.T) {
client := newTestClient(fakeRT)
var buf bytes.Buffer
opts := BuildImageOptions{
Name: "testImage",
NoCache: true,
SuppressOutput: true,
RmTmpContainer: true,
InputStream: &buf,
OutputStream: &buf,
Name: "testImage",
NoCache: true,
SuppressOutput: true,
RmTmpContainer: true,
ForceRmTmpContainer: true,
InputStream: &buf,
OutputStream: &buf,
}
err := client.BuildImage(opts)
if err != nil && strings.Index(err.Error(), "build image fail") == -1 {
t.Fatal(err)
}
req := fakeRT.requests[0]
expected := map[string][]string{"t": {opts.Name}, "nocache": {"1"}, "q": {"1"}, "rm": {"1"}}
expected := map[string][]string{"t": {opts.Name}, "nocache": {"1"}, "q": {"1"}, "rm": {"1"}, "forcerm": {"1"}}
got := map[string][]string(req.URL.Query())
if !reflect.DeepEqual(got, expected) {
t.Errorf("BuildImage: wrong query string. Want %#v. Got %#v.", expected, got)
@ -640,3 +668,45 @@ func TestIsUrl(t *testing.T) {
t.Errorf("isURL: wrong match. Expected %#v to not be a url. Got %#v", url, result)
}
}
func TestLoadImage(t *testing.T) {
fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
client := newTestClient(fakeRT)
tar, err := os.Open("testing/data/container.tar")
if err != nil {
t.Fatal(err)
} else {
defer tar.Close()
}
opts := LoadImageOptions{InputStream: tar}
err = client.LoadImage(opts)
if nil != err {
t.Error(err)
}
req := fakeRT.requests[0]
if req.Method != "POST" {
t.Errorf("LoadImage: wrong method. Expected %q. Got %q.", "POST", req.Method)
}
if req.URL.Path != "/images/load" {
t.Errorf("LoadImage: wrong URL. Expected %q. Got %q.", "/images/load", req.URL.Path)
}
}
func TestExportImage(t *testing.T) {
var buf bytes.Buffer
fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
client := newTestClient(fakeRT)
opts := ExportImageOptions{Name: "testimage", OutputStream: &buf}
err := client.ExportImage(opts)
if nil != err {
t.Error(err)
}
req := fakeRT.requests[0]
if req.Method != "GET" {
t.Errorf("ExportImage: wrong method. Expected %q. Got %q.", "GET", req.Method)
}
expectedPath := "/images/testimage/get"
if req.URL.Path != expectedPath {
t.Errorf("ExportIMage: wrong path. Expected %q. Got %q.", expectedPath, req.URL.Path)
}
}

View File

@ -12,8 +12,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/fsouza/go-dockerclient"
"github.com/gorilla/mux"
mathrand "math/rand"
"net"
"net/http"
@ -22,6 +20,9 @@ import (
"strings"
"sync"
"time"
"github.com/fsouza/go-dockerclient"
"github.com/gorilla/mux"
)
// DockerServer represents a programmable, concurrent (not much), HTTP server
@ -102,6 +103,8 @@ func (s *DockerServer) buildMuxer() {
s.mux.Path("/images/{name:.*}/push").Methods("POST").HandlerFunc(s.handlerWrapper(s.pushImage))
s.mux.Path("/events").Methods("GET").HandlerFunc(s.listEvents)
s.mux.Path("/_ping").Methods("GET").HandlerFunc(s.handlerWrapper(s.pingDocker))
s.mux.Path("/images/load").Methods("POST").HandlerFunc(s.handlerWrapper(s.loadImage))
s.mux.Path("/images/{id:.*}/get").Methods("GET").HandlerFunc(s.handlerWrapper(s.getImage))
}
// PrepareFailure adds a new expected failure based on a URL regexp it receives
@ -653,3 +656,13 @@ func (s *DockerServer) generateEvent() *docker.APIEvents {
Time: time.Now().Unix(),
}
}
func (s *DockerServer) loadImage(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}
func (s *DockerServer) getImage(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/tar")
}

View File

@ -7,7 +7,6 @@ package testing
import (
"encoding/json"
"fmt"
"github.com/fsouza/go-dockerclient"
"math/rand"
"net"
"net/http"
@ -17,6 +16,8 @@ import (
"strings"
"testing"
"time"
"github.com/fsouza/go-dockerclient"
)
func TestNewServer(t *testing.T) {

View File

@ -17,10 +17,10 @@ limitations under the License.
package v1beta1
import (
"github.com/fsouza/go-dockerclient"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
"github.com/GoogleCloudPlatform/kubernetes/third_party/docker-api-structs"
)
// Common string formats

View File

@ -1,22 +0,0 @@
Copyright (c) 2014, go-dockerclient authors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1 +0,0 @@
This package is a fork of part of [go-dockerclient](https://github.com/fsouza/go-dockerclient).

View File

@ -1,104 +0,0 @@
// Copyright 2014 go-dockerclient authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package docker
import (
"time"
)
type Container struct {
ID string `yaml:"ID,omitempty" json:"ID,omitempty"`
Created time.Time `yaml:"Created,omitempty" json:"Created,omitempty"`
Path string `yaml:"Path,omitempty" json:"Path,omitempty"`
Args []string `yaml:"Args,omitempty" json:"Args,omitempty"`
Config *Config `yaml:"Config,omitempty" json:"Config,omitempty"`
State State `yaml:"State,omitempty" json:"State,omitempty"`
Image string `yaml:"Image,omitempty" json:"Image,omitempty"`
NetworkSettings *NetworkSettings `yaml:"NetworkSettings,omitempty" json:"NetworkSettings,omitempty"`
SysInitPath string `yaml:"SysInitPath,omitempty" json:"SysInitPath,omitempty"`
ResolvConfPath string `yaml:"ResolvConfPath,omitempty" json:"ResolvConfPath,omitempty"`
HostnamePath string `yaml:"HostnamePath,omitempty" json:"HostnamePath,omitempty"`
HostsPath string `yaml:"HostsPath,omitempty" json:"HostsPath,omitempty"`
Name string `yaml:"Name,omitempty" json:"Name,omitempty"`
Driver string `yaml:"Driver,omitempty" json:"Driver,omitempty"`
Volumes map[string]string `yaml:"Volumes,omitempty" json:"Volumes,omitempty"`
VolumesRW map[string]bool `yaml:"VolumesRW,omitempty" json:"VolumesRW,omitempty"`
HostConfig *HostConfig `yaml:"HostConfig,omitempty" json:"HostConfig,omitempty"`
}
type Config struct {
Hostname string `yaml:"Hostname,omitempty" json:"Hostname,omitempty"`
Domainname string `yaml:"Domainname,omitempty" json:"Domainname,omitempty"`
User string `yaml:"User,omitempty" json:"User,omitempty"`
Memory int64 `yaml:"Memory,omitempty" json:"Memory,omitempty"`
MemorySwap int64 `yaml:"MemorySwap,omitempty" json:"MemorySwap,omitempty"`
CpuShares int64 `yaml:"CpuShares,omitempty" json:"CpuShares,omitempty"`
AttachStdin bool `yaml:"AttachStdin,omitempty" json:"AttachStdin,omitempty"`
AttachStdout bool `yaml:"AttachStdout,omitempty" json:"AttachStdout,omitempty"`
AttachStderr bool `yaml:"AttachStderr,omitempty" json:"AttachStderr,omitempty"`
PortSpecs []string `yaml:"PortSpecs,omitempty" json:"PortSpecs,omitempty"`
ExposedPorts map[Port]struct{} `yaml:"ExposedPorts,omitempty" json:"ExposedPorts,omitempty"`
Tty bool `yaml:"Tty,omitempty" json:"Tty,omitempty"`
OpenStdin bool `yaml:"OpenStdin,omitempty" json:"OpenStdin,omitempty"`
StdinOnce bool `yaml:"StdinOnce,omitempty" json:"StdinOnce,omitempty"`
Env []string `yaml:"Env,omitempty" json:"Env,omitempty"`
Cmd []string `yaml:"Cmd,omitempty" json:"Cmd,omitempty"`
Dns []string `yaml:"Dns,omitempty" json:"Dns,omitempty"`
Image string `yaml:"Image,omitempty" json:"Image,omitempty"`
Volumes map[string]struct{} `yaml:"Volumes,omitempty" json:"Volumes,omitempty"`
VolumesFrom string `yaml:"VolumesFrom,omitempty" json:"VolumesFrom,omitempty"`
WorkingDir string `yaml:"WorkingDir,omitempty" json:"WorkingDir,omitempty"`
Entrypoint []string `yaml:"Entrypoint,omitempty" json:"Entrypoint,omitempty"`
NetworkDisabled bool `yaml:"NetworkDisabled,omitempty" json:"NetworkDisabled,omitempty"`
}
type State struct {
Running bool `yaml:"Running,omitempty" json:"Running,omitempty"`
Paused bool `yaml:"Paused,omitempty" json:"Paused,omitempty"`
Pid int `yaml:"Pid,omitempty" json:"Pid,omitempty"`
ExitCode int `yaml:"ExitCode,omitempty" json:"ExitCode,omitempty"`
StartedAt time.Time `yaml:"StartedAt,omitempty" json:"StartedAt,omitempty"`
FinishedAt time.Time `yaml:"FinishedAt,omitempty" json:"FinishedAt,omitempty"`
}
type PortBinding struct {
HostIp string `yaml:"HostIp,omitempty" json:"HostIp,omitempty"`
HostPort string `yaml:"HostPort,omitempty" json:"HostPort,omitempty"`
}
type PortMapping map[string]string
type NetworkSettings struct {
IPAddress string `yaml:"IPAddress,omitempty" json:"IPAddress,omitempty"`
IPPrefixLen int `yaml:"IPPrefixLen,omitempty" json:"IPPrefixLen,omitempty"`
Gateway string `yaml:"Gateway,omitempty" json:"Gateway,omitempty"`
Bridge string `yaml:"Bridge,omitempty" json:"Bridge,omitempty"`
PortMapping map[string]PortMapping `yaml:"PortMapping,omitempty" json:"PortMapping,omitempty"`
Ports map[Port][]PortBinding `yaml:"Ports,omitempty" json:"Ports,omitempty"`
}
type KeyValuePair struct {
Key string `yaml:"Key,omitempty" json:"Key,omitempty"`
Value string `yaml:"Value,omitempty" json:"Value,omitempty"`
}
type Port string
type HostConfig struct {
Binds []string `yaml:"Binds,omitempty" json:"Binds,omitempty"`
ContainerIDFile string `yaml:"ContainerIDFile,omitempty" json:"ContainerIDFile,omitempty"`
LxcConf []KeyValuePair `yaml:"LxcConf,omitempty" json:"LxcConf,omitempty"`
Privileged bool `yaml:"Privileged,omitempty" json:"Privileged,omitempty"`
PortBindings map[Port][]PortBinding `yaml:"PortBindings,omitempty" json:"PortBindings,omitempty"`
Links []string `yaml:"Links,omitempty" json:"Links,omitempty"`
PublishAllPorts bool `yaml:"PublishAllPorts,omitempty" json:"PublishAllPorts,omitempty"`
Dns []string `yaml:"Dns,omitempty" json:"Dns,omitempty"`
DnsSearch []string `yaml:"DnsSearch,omitempty" json:"DnsSearch,omitempty"`
VolumesFrom []string `yaml:"VolumesFrom,omitempty" json:"VolumesFrom,omitempty"`
NetworkMode string `yaml:"NetworkMode,omitempty" json:"NetworkMode,omitempty"`
}