mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Really upgrade fsouza/go-dockerclient pkg to latest revision, so that we can have
Error and OOMKilled from docker ContainerStatus.
This commit is contained in:
parent
b489757b5a
commit
95e3efdad8
4
Godeps/Godeps.json
generated
4
Godeps/Godeps.json
generated
@ -104,8 +104,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/fsouza/go-dockerclient",
|
"ImportPath": "github.com/fsouza/go-dockerclient",
|
||||||
"Comment": "0.2.1-267-g15d2c6e",
|
"Comment": "0.2.1-334-g9c377ff",
|
||||||
"Rev": "15d2c6e3eb670c545d0af0604d7f9aff3871af04"
|
"Rev": "9c377ffd9aed48a012adf1c3fd517fe98394120b"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/ghodss/yaml",
|
"ImportPath": "github.com/ghodss/yaml",
|
||||||
|
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/.travis.yml
generated
vendored
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/.travis.yml
generated
vendored
@ -1,6 +1,5 @@
|
|||||||
language: go
|
language: go
|
||||||
go:
|
go:
|
||||||
- 1.1.2
|
|
||||||
- 1.2.2
|
- 1.2.2
|
||||||
- 1.3.1
|
- 1.3.1
|
||||||
- tip
|
- tip
|
||||||
@ -11,3 +10,4 @@ install:
|
|||||||
- go get -d ./...
|
- go get -d ./...
|
||||||
script:
|
script:
|
||||||
- go test ./...
|
- go test ./...
|
||||||
|
- ./testing/bin/fmtpolice
|
||||||
|
8
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/AUTHORS
generated
vendored
8
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/AUTHORS
generated
vendored
@ -12,6 +12,7 @@ cheneydeng <cheneydeng@qq.com>
|
|||||||
CMGS <ilskdw@gmail.com>
|
CMGS <ilskdw@gmail.com>
|
||||||
Daniel, Dao Quang Minh <dqminh89@gmail.com>
|
Daniel, Dao Quang Minh <dqminh89@gmail.com>
|
||||||
David Huie <dahuie@gmail.com>
|
David Huie <dahuie@gmail.com>
|
||||||
|
Dawn Chen <dawnchen@google.com>
|
||||||
Ed <edrocksit@gmail.com>
|
Ed <edrocksit@gmail.com>
|
||||||
Eric Anderson <anderson@copperegg.com>
|
Eric Anderson <anderson@copperegg.com>
|
||||||
Fabio Rehm <fgrehm@gmail.com>
|
Fabio Rehm <fgrehm@gmail.com>
|
||||||
@ -19,6 +20,7 @@ Flavia Missi <flaviamissi@gmail.com>
|
|||||||
Francisco Souza <f@souza.cc>
|
Francisco Souza <f@souza.cc>
|
||||||
Jari Kolehmainen <jari.kolehmainen@digia.com>
|
Jari Kolehmainen <jari.kolehmainen@digia.com>
|
||||||
Jason Wilder <jwilder@litl.com>
|
Jason Wilder <jwilder@litl.com>
|
||||||
|
Jawher Moussa <jawher.moussa@gmail.com>
|
||||||
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
|
Jean-Baptiste Dalido <jeanbaptiste@appgratis.com>
|
||||||
Jeff Mitchell <jeffrey.mitchell@gmail.com>
|
Jeff Mitchell <jeffrey.mitchell@gmail.com>
|
||||||
Jeffrey Hulten <jhulten@gmail.com>
|
Jeffrey Hulten <jhulten@gmail.com>
|
||||||
@ -26,11 +28,14 @@ Johan Euphrosine <proppy@google.com>
|
|||||||
Karan Misra <kidoman@gmail.com>
|
Karan Misra <kidoman@gmail.com>
|
||||||
Kim, Hirokuni <hirokuni.kim@kvh.co.jp>
|
Kim, Hirokuni <hirokuni.kim@kvh.co.jp>
|
||||||
Lucas Clemente <lucas@clemente.io>
|
Lucas Clemente <lucas@clemente.io>
|
||||||
|
Máximo Cuadros Ortiz <mcuadros@gmail.com>
|
||||||
|
Mike Dillon <mike.dillon@synctree.com>
|
||||||
Omeid Matten <public@omeid.me>
|
Omeid Matten <public@omeid.me>
|
||||||
Paul Morie <pmorie@gmail.com>
|
Paul Morie <pmorie@gmail.com>
|
||||||
Peter Jihoon Kim <raingrove@gmail.com>
|
Peter Jihoon Kim <raingrove@gmail.com>
|
||||||
Philippe Lafoucrière <philippe.lafoucriere@tech-angels.com>
|
Philippe Lafoucrière <philippe.lafoucriere@tech-angels.com>
|
||||||
Rafe Colton <r.colton@modcloth.com>
|
Rafe Colton <rafael.colton@gmail.com>
|
||||||
|
Rob Miller <rob@kalistra.com>
|
||||||
Robert Williamson <williamson.robert@gmail.com>
|
Robert Williamson <williamson.robert@gmail.com>
|
||||||
Salvador Gironès <salvadorgirones@gmail.com>
|
Salvador Gironès <salvadorgirones@gmail.com>
|
||||||
Simon Eskildsen <sirup@sirupsen.com>
|
Simon Eskildsen <sirup@sirupsen.com>
|
||||||
@ -42,3 +47,4 @@ Summer Mousa <smousa@zenoss.com>
|
|||||||
Tarsis Azevedo <tarsis@corp.globo.com>
|
Tarsis Azevedo <tarsis@corp.globo.com>
|
||||||
Tim Schindler <tim@catalyst-zero.com>
|
Tim Schindler <tim@catalyst-zero.com>
|
||||||
Wiliam Souza <wiliamsouza83@gmail.com>
|
Wiliam Souza <wiliamsouza83@gmail.com>
|
||||||
|
Ye Yin <eyniy@qq.com>
|
||||||
|
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/README.markdown
generated
vendored
2
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/README.markdown
generated
vendored
@ -29,7 +29,7 @@ func main() {
|
|||||||
fmt.Println("Created: ", img.Created)
|
fmt.Println("Created: ", img.Created)
|
||||||
fmt.Println("Size: ", img.Size)
|
fmt.Println("Size: ", img.Size)
|
||||||
fmt.Println("VirtualSize: ", img.VirtualSize)
|
fmt.Println("VirtualSize: ", img.VirtualSize)
|
||||||
fmt.Println("ParentId: ", img.ParentId)
|
fmt.Println("ParentId: ", img.ParentID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
144
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/build_test.go
generated
vendored
Normal file
144
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/build_test.go
generated
vendored
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
package docker
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/archive"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuildImageMultipleContextsError(t *testing.T) {
|
||||||
|
fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
|
||||||
|
client := newTestClient(fakeRT)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
opts := BuildImageOptions{
|
||||||
|
Name: "testImage",
|
||||||
|
NoCache: true,
|
||||||
|
SuppressOutput: true,
|
||||||
|
RmTmpContainer: true,
|
||||||
|
ForceRmTmpContainer: true,
|
||||||
|
InputStream: &buf,
|
||||||
|
OutputStream: &buf,
|
||||||
|
ContextDir: "testing/data",
|
||||||
|
}
|
||||||
|
err := client.BuildImage(opts)
|
||||||
|
if err != ErrMultipleContexts {
|
||||||
|
t.Errorf("BuildImage: providing both InputStream and ContextDir should produce an error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildImageContextDirDockerignoreParsing(t *testing.T) {
|
||||||
|
fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
|
||||||
|
client := newTestClient(fakeRT)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
opts := BuildImageOptions{
|
||||||
|
Name: "testImage",
|
||||||
|
NoCache: true,
|
||||||
|
SuppressOutput: true,
|
||||||
|
RmTmpContainer: true,
|
||||||
|
ForceRmTmpContainer: true,
|
||||||
|
OutputStream: &buf,
|
||||||
|
ContextDir: "testing/data",
|
||||||
|
}
|
||||||
|
err := client.BuildImage(opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
reqBody := fakeRT.requests[0].Body
|
||||||
|
tmpdir, err := unpackBodyTarball(reqBody)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := os.RemoveAll(tmpdir); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
files, err := ioutil.ReadDir(tmpdir)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
foundFiles := []string{}
|
||||||
|
for _, file := range files {
|
||||||
|
foundFiles = append(foundFiles, file.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
expectedFiles := []string{
|
||||||
|
".dockerignore",
|
||||||
|
"Dockerfile",
|
||||||
|
"barfile",
|
||||||
|
"ca.pem",
|
||||||
|
"cert.pem",
|
||||||
|
"key.pem",
|
||||||
|
"server.pem",
|
||||||
|
"serverkey.pem",
|
||||||
|
"symlink",
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(expectedFiles, foundFiles) {
|
||||||
|
t.Errorf(
|
||||||
|
"BuildImage: incorrect files sent in tarball to docker server\nexpected %+v, found %+v",
|
||||||
|
expectedFiles, foundFiles,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBuildImageSendXRegistryConfig(t *testing.T) {
|
||||||
|
fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
|
||||||
|
client := newTestClient(fakeRT)
|
||||||
|
var buf bytes.Buffer
|
||||||
|
opts := BuildImageOptions{
|
||||||
|
Name: "testImage",
|
||||||
|
NoCache: true,
|
||||||
|
SuppressOutput: true,
|
||||||
|
RmTmpContainer: true,
|
||||||
|
ForceRmTmpContainer: true,
|
||||||
|
OutputStream: &buf,
|
||||||
|
ContextDir: "testing/data",
|
||||||
|
AuthConfigs: AuthConfigurations{
|
||||||
|
Configs: map[string]AuthConfiguration{
|
||||||
|
"quay.io": {
|
||||||
|
Username: "foo",
|
||||||
|
Password: "bar",
|
||||||
|
Email: "baz",
|
||||||
|
ServerAddress: "quay.io",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
encodedConfig := "eyJjb25maWdzIjp7InF1YXkuaW8iOnsidXNlcm5hbWUiOiJmb28iLCJwYXNzd29yZCI6ImJhciIsImVtYWlsIjoiYmF6Iiwic2VydmVyYWRkcmVzcyI6InF1YXkuaW8ifX19Cg=="
|
||||||
|
|
||||||
|
if err := client.BuildImage(opts); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
xRegistryConfig := fakeRT.requests[0].Header["X-Registry-Config"][0]
|
||||||
|
if xRegistryConfig != encodedConfig {
|
||||||
|
t.Errorf(
|
||||||
|
"BuildImage: X-Registry-Config not set currectly: expected %q, got %q",
|
||||||
|
encodedConfig,
|
||||||
|
xRegistryConfig,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpackBodyTarball(req io.ReadCloser) (tmpdir string, err error) {
|
||||||
|
tmpdir, err = ioutil.TempDir("", "go-dockerclient-test")
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = archive.Untar(req, tmpdir, &archive.TarOptions{
|
||||||
|
Compression: archive.Uncompressed,
|
||||||
|
NoLchown: true,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
7
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/change.go
generated
vendored
7
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/change.go
generated
vendored
@ -6,11 +6,18 @@ package docker
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
|
// ChangeType is a type for constants indicating the type of change
|
||||||
|
// in a container
|
||||||
type ChangeType int
|
type ChangeType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// ChangeModify is the ChangeType for container modifications
|
||||||
ChangeModify ChangeType = iota
|
ChangeModify ChangeType = iota
|
||||||
|
|
||||||
|
// ChangeAdd is the ChangeType for additions to a container
|
||||||
ChangeAdd
|
ChangeAdd
|
||||||
|
|
||||||
|
// ChangeDelete is the ChangeType for deletions from a container
|
||||||
ChangeDelete
|
ChangeDelete
|
||||||
)
|
)
|
||||||
|
|
||||||
|
166
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/client.go
generated
vendored
166
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/client.go
generated
vendored
@ -9,6 +9,8 @@ package docker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -32,22 +34,22 @@ var (
|
|||||||
// ErrConnectionRefused is returned when the client cannot connect to the given endpoint.
|
// ErrConnectionRefused is returned when the client cannot connect to the given endpoint.
|
||||||
ErrConnectionRefused = errors.New("cannot connect to Docker endpoint")
|
ErrConnectionRefused = errors.New("cannot connect to Docker endpoint")
|
||||||
|
|
||||||
apiVersion_1_12, _ = NewApiVersion("1.12")
|
apiVersion1_12, _ = NewAPIVersion("1.12")
|
||||||
)
|
)
|
||||||
|
|
||||||
// ApiVersion is an internal representation of a version of the Remote API.
|
// APIVersion is an internal representation of a version of the Remote API.
|
||||||
type ApiVersion []int
|
type APIVersion []int
|
||||||
|
|
||||||
// NewApiVersion returns an instance of ApiVersion for the given string.
|
// NewAPIVersion returns an instance of APIVersion for the given string.
|
||||||
//
|
//
|
||||||
// The given string must be in the form <major>.<minor>.<patch>, where <major>,
|
// The given string must be in the form <major>.<minor>.<patch>, where <major>,
|
||||||
// <minor> and <patch> are integer numbers.
|
// <minor> and <patch> are integer numbers.
|
||||||
func NewApiVersion(input string) (ApiVersion, error) {
|
func NewAPIVersion(input string) (APIVersion, error) {
|
||||||
if !strings.Contains(input, ".") {
|
if !strings.Contains(input, ".") {
|
||||||
return nil, fmt.Errorf("Unable to parse version %q", input)
|
return nil, fmt.Errorf("Unable to parse version %q", input)
|
||||||
}
|
}
|
||||||
arr := strings.Split(input, ".")
|
arr := strings.Split(input, ".")
|
||||||
ret := make(ApiVersion, len(arr))
|
ret := make(APIVersion, len(arr))
|
||||||
var err error
|
var err error
|
||||||
for i, val := range arr {
|
for i, val := range arr {
|
||||||
ret[i], err = strconv.Atoi(val)
|
ret[i], err = strconv.Atoi(val)
|
||||||
@ -58,7 +60,7 @@ func NewApiVersion(input string) (ApiVersion, error) {
|
|||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (version ApiVersion) String() string {
|
func (version APIVersion) String() string {
|
||||||
var str string
|
var str string
|
||||||
for i, val := range version {
|
for i, val := range version {
|
||||||
str += strconv.Itoa(val)
|
str += strconv.Itoa(val)
|
||||||
@ -69,23 +71,27 @@ func (version ApiVersion) String() string {
|
|||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
func (version ApiVersion) LessThan(other ApiVersion) bool {
|
// LessThan is a function for comparing APIVersion structs
|
||||||
|
func (version APIVersion) LessThan(other APIVersion) bool {
|
||||||
return version.compare(other) < 0
|
return version.compare(other) < 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (version ApiVersion) LessThanOrEqualTo(other ApiVersion) bool {
|
// LessThanOrEqualTo is a function for comparing APIVersion structs
|
||||||
|
func (version APIVersion) LessThanOrEqualTo(other APIVersion) bool {
|
||||||
return version.compare(other) <= 0
|
return version.compare(other) <= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (version ApiVersion) GreaterThan(other ApiVersion) bool {
|
// GreaterThan is a function for comparing APIVersion structs
|
||||||
|
func (version APIVersion) GreaterThan(other APIVersion) bool {
|
||||||
return version.compare(other) > 0
|
return version.compare(other) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (version ApiVersion) GreaterThanOrEqualTo(other ApiVersion) bool {
|
// GreaterThanOrEqualTo is a function for comparing APIVersion structs
|
||||||
|
func (version APIVersion) GreaterThanOrEqualTo(other APIVersion) bool {
|
||||||
return version.compare(other) >= 0
|
return version.compare(other) >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (version ApiVersion) compare(other ApiVersion) int {
|
func (version APIVersion) compare(other APIVersion) int {
|
||||||
for i, v := range version {
|
for i, v := range version {
|
||||||
if i <= len(other)-1 {
|
if i <= len(other)-1 {
|
||||||
otherVersion := other[i]
|
otherVersion := other[i]
|
||||||
@ -111,13 +117,14 @@ func (version ApiVersion) compare(other ApiVersion) int {
|
|||||||
type Client struct {
|
type Client struct {
|
||||||
SkipServerVersionCheck bool
|
SkipServerVersionCheck bool
|
||||||
HTTPClient *http.Client
|
HTTPClient *http.Client
|
||||||
|
TLSConfig *tls.Config
|
||||||
|
|
||||||
endpoint string
|
endpoint string
|
||||||
endpointURL *url.URL
|
endpointURL *url.URL
|
||||||
eventMonitor *eventMonitoringState
|
eventMonitor *eventMonitoringState
|
||||||
requestedApiVersion ApiVersion
|
requestedAPIVersion APIVersion
|
||||||
serverApiVersion ApiVersion
|
serverAPIVersion APIVersion
|
||||||
expectedApiVersion ApiVersion
|
expectedAPIVersion APIVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewClient returns a Client instance ready for communication with the given
|
// NewClient returns a Client instance ready for communication with the given
|
||||||
@ -132,6 +139,18 @@ func NewClient(endpoint string) (*Client, error) {
|
|||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewTLSClient returns a Client instance ready for TLS communications with the givens
|
||||||
|
// server endpoint, key and certificates . It will use the latest remote API version
|
||||||
|
// available in the server.
|
||||||
|
func NewTLSClient(endpoint string, cert, key, ca string) (*Client, error) {
|
||||||
|
client, err := NewVersionnedTLSClient(endpoint, cert, key, ca, "")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
client.SkipServerVersionCheck = true
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
// NewVersionedClient returns a Client instance ready for communication with
|
// NewVersionedClient returns a Client instance ready for communication with
|
||||||
// the given server endpoint, using a specific remote API version.
|
// the given server endpoint, using a specific remote API version.
|
||||||
func NewVersionedClient(endpoint string, apiVersionString string) (*Client, error) {
|
func NewVersionedClient(endpoint string, apiVersionString string) (*Client, error) {
|
||||||
@ -139,9 +158,9 @@ func NewVersionedClient(endpoint string, apiVersionString string) (*Client, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var requestedApiVersion ApiVersion
|
var requestedAPIVersion APIVersion
|
||||||
if strings.Contains(apiVersionString, ".") {
|
if strings.Contains(apiVersionString, ".") {
|
||||||
requestedApiVersion, err = NewApiVersion(apiVersionString)
|
requestedAPIVersion, err = NewAPIVersion(apiVersionString)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -151,23 +170,74 @@ func NewVersionedClient(endpoint string, apiVersionString string) (*Client, erro
|
|||||||
endpoint: endpoint,
|
endpoint: endpoint,
|
||||||
endpointURL: u,
|
endpointURL: u,
|
||||||
eventMonitor: new(eventMonitoringState),
|
eventMonitor: new(eventMonitoringState),
|
||||||
requestedApiVersion: requestedApiVersion,
|
requestedAPIVersion: requestedAPIVersion,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) checkApiVersion() error {
|
// NewVersionnedTLSClient returns a Client instance ready for TLS communications with the givens
|
||||||
serverApiVersionString, err := c.getServerApiVersionString()
|
// server endpoint, key and certificates, using a specific remote API version.
|
||||||
|
func NewVersionnedTLSClient(endpoint string, cert, key, ca, apiVersionString string) (*Client, error) {
|
||||||
|
u, err := parseEndpoint(endpoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
c.serverApiVersion, err = NewApiVersion(serverApiVersionString)
|
var requestedAPIVersion APIVersion
|
||||||
|
if strings.Contains(apiVersionString, ".") {
|
||||||
|
requestedAPIVersion, err = NewAPIVersion(apiVersionString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cert == "" || key == "" {
|
||||||
|
return nil, errors.New("Both cert and key path are required")
|
||||||
|
}
|
||||||
|
tlsCert, err := tls.LoadX509KeyPair(cert, key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
if c.requestedApiVersion == nil {
|
tlsConfig := &tls.Config{Certificates: []tls.Certificate{tlsCert}}
|
||||||
c.expectedApiVersion = c.serverApiVersion
|
if ca == "" {
|
||||||
|
tlsConfig.InsecureSkipVerify = true
|
||||||
} else {
|
} else {
|
||||||
c.expectedApiVersion = c.requestedApiVersion
|
cert, err := ioutil.ReadFile(ca)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
caPool := x509.NewCertPool()
|
||||||
|
if !caPool.AppendCertsFromPEM(cert) {
|
||||||
|
return nil, errors.New("Could not add RootCA pem")
|
||||||
|
}
|
||||||
|
tlsConfig.RootCAs = caPool
|
||||||
|
}
|
||||||
|
tr := &http.Transport{
|
||||||
|
TLSClientConfig: tlsConfig,
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Client{
|
||||||
|
HTTPClient: &http.Client{Transport: tr},
|
||||||
|
TLSConfig: tlsConfig,
|
||||||
|
endpoint: endpoint,
|
||||||
|
endpointURL: u,
|
||||||
|
eventMonitor: new(eventMonitoringState),
|
||||||
|
requestedAPIVersion: requestedAPIVersion,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) checkAPIVersion() error {
|
||||||
|
serverAPIVersionString, err := c.getServerAPIVersionString()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.serverAPIVersion, err = NewAPIVersion(serverAPIVersionString)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if c.requestedAPIVersion == nil {
|
||||||
|
c.expectedAPIVersion = c.serverAPIVersion
|
||||||
|
} else {
|
||||||
|
c.expectedAPIVersion = c.requestedAPIVersion
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -187,7 +257,7 @@ func (c *Client) Ping() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) getServerApiVersionString() (version string, err error) {
|
func (c *Client) getServerAPIVersionString() (version string, err error) {
|
||||||
body, status, err := c.do("GET", "/version", nil)
|
body, status, err := c.do("GET", "/version", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -213,8 +283,8 @@ func (c *Client) do(method, path string, data interface{}) ([]byte, int, error)
|
|||||||
}
|
}
|
||||||
params = bytes.NewBuffer(buf)
|
params = bytes.NewBuffer(buf)
|
||||||
}
|
}
|
||||||
if path != "/version" && !c.SkipServerVersionCheck && c.expectedApiVersion == nil {
|
if path != "/version" && !c.SkipServerVersionCheck && c.expectedAPIVersion == nil {
|
||||||
err := c.checkApiVersion()
|
err := c.checkAPIVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, -1, err
|
return nil, -1, err
|
||||||
}
|
}
|
||||||
@ -268,8 +338,8 @@ func (c *Client) stream(method, path string, setRawTerminal, rawJSONStream bool,
|
|||||||
if (method == "POST" || method == "PUT") && in == nil {
|
if (method == "POST" || method == "PUT") && in == nil {
|
||||||
in = bytes.NewReader(nil)
|
in = bytes.NewReader(nil)
|
||||||
}
|
}
|
||||||
if path != "/version" && !c.SkipServerVersionCheck && c.expectedApiVersion == nil {
|
if path != "/version" && !c.SkipServerVersionCheck && c.expectedAPIVersion == nil {
|
||||||
err := c.checkApiVersion()
|
err := c.checkAPIVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -357,8 +427,8 @@ func (c *Client) stream(method, path string, setRawTerminal, rawJSONStream bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) hijack(method, path string, success chan struct{}, setRawTerminal bool, in io.Reader, stderr, stdout io.Writer, data interface{}) error {
|
func (c *Client) hijack(method, path string, success chan struct{}, setRawTerminal bool, in io.Reader, stderr, stdout io.Writer, data interface{}) error {
|
||||||
if path != "/version" && !c.SkipServerVersionCheck && c.expectedApiVersion == nil {
|
if path != "/version" && !c.SkipServerVersionCheck && c.expectedAPIVersion == nil {
|
||||||
err := c.checkApiVersion()
|
err := c.checkAPIVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -434,11 +504,10 @@ func (c *Client) getURL(path string) string {
|
|||||||
urlStr = ""
|
urlStr = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.requestedApiVersion != nil {
|
if c.requestedAPIVersion != nil {
|
||||||
return fmt.Sprintf("%s/v%s%s", urlStr, c.requestedApiVersion, path)
|
return fmt.Sprintf("%s/v%s%s", urlStr, c.requestedAPIVersion, path)
|
||||||
} else {
|
|
||||||
return fmt.Sprintf("%s%s", urlStr, path)
|
|
||||||
}
|
}
|
||||||
|
return fmt.Sprintf("%s%s", urlStr, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
type jsonMessage struct {
|
type jsonMessage struct {
|
||||||
@ -495,6 +564,12 @@ func queryString(opts interface{}) string {
|
|||||||
items.Add(key, string(b))
|
items.Add(key, string(b))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case reflect.Map:
|
||||||
|
if len(v.MapKeys()) > 0 {
|
||||||
|
if b, err := json.Marshal(v.Interface()); err == nil {
|
||||||
|
items.Add(key, string(b))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items.Encode()
|
return items.Encode()
|
||||||
@ -520,7 +595,22 @@ func parseEndpoint(endpoint string) (*url.URL, error) {
|
|||||||
return nil, ErrInvalidEndpoint
|
return nil, ErrInvalidEndpoint
|
||||||
}
|
}
|
||||||
if u.Scheme == "tcp" {
|
if u.Scheme == "tcp" {
|
||||||
u.Scheme = "http"
|
_, port, err := net.SplitHostPort(u.Host)
|
||||||
|
if err != nil {
|
||||||
|
if e, ok := err.(*net.AddrError); ok {
|
||||||
|
if e.Err == "missing port in address" {
|
||||||
|
return u, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, ErrInvalidEndpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
number, err := strconv.ParseInt(port, 10, 64)
|
||||||
|
if err == nil && number == 2376 {
|
||||||
|
u.Scheme = "https"
|
||||||
|
} else {
|
||||||
|
u.Scheme = "http"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "unix" {
|
if u.Scheme != "http" && u.Scheme != "https" && u.Scheme != "unix" {
|
||||||
return nil, ErrInvalidEndpoint
|
return nil, ErrInvalidEndpoint
|
||||||
|
98
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/client_test.go
generated
vendored
98
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/client_test.go
generated
vendored
@ -39,8 +39,32 @@ func TestNewAPIClient(t *testing.T) {
|
|||||||
if !client.SkipServerVersionCheck {
|
if !client.SkipServerVersionCheck {
|
||||||
t.Error("Expected SkipServerVersionCheck to be true, got false")
|
t.Error("Expected SkipServerVersionCheck to be true, got false")
|
||||||
}
|
}
|
||||||
if client.requestedApiVersion != nil {
|
if client.requestedAPIVersion != nil {
|
||||||
t.Errorf("Expected requestedApiVersion to be nil, got %#v.", client.requestedApiVersion)
|
t.Errorf("Expected requestedAPIVersion to be nil, got %#v.", client.requestedAPIVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTLSClient(endpoint string) (*Client, error) {
|
||||||
|
return NewTLSClient(endpoint,
|
||||||
|
"testing/data/cert.pem",
|
||||||
|
"testing/data/key.pem",
|
||||||
|
"testing/data/ca.pem")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewTSLAPIClient(t *testing.T) {
|
||||||
|
endpoint := "https://localhost:4243"
|
||||||
|
client, err := newTLSClient(endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if client.endpoint != endpoint {
|
||||||
|
t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
|
||||||
|
}
|
||||||
|
if !client.SkipServerVersionCheck {
|
||||||
|
t.Error("Expected SkipServerVersionCheck to be true, got false")
|
||||||
|
}
|
||||||
|
if client.requestedAPIVersion != nil {
|
||||||
|
t.Errorf("Expected requestedAPIVersion to be nil, got %#v.", client.requestedAPIVersion)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,14 +80,45 @@ func TestNewVersionedClient(t *testing.T) {
|
|||||||
if client.HTTPClient != http.DefaultClient {
|
if client.HTTPClient != http.DefaultClient {
|
||||||
t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.HTTPClient)
|
t.Errorf("Expected http.Client %#v. Got %#v.", http.DefaultClient, client.HTTPClient)
|
||||||
}
|
}
|
||||||
if reqVersion := client.requestedApiVersion.String(); reqVersion != "1.12" {
|
if reqVersion := client.requestedAPIVersion.String(); reqVersion != "1.12" {
|
||||||
t.Errorf("Wrong requestApiVersion. Want %q. Got %q.", "1.12", reqVersion)
|
t.Errorf("Wrong requestAPIVersion. Want %q. Got %q.", "1.12", reqVersion)
|
||||||
}
|
}
|
||||||
if client.SkipServerVersionCheck {
|
if client.SkipServerVersionCheck {
|
||||||
t.Error("Expected SkipServerVersionCheck to be false, got true")
|
t.Error("Expected SkipServerVersionCheck to be false, got true")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewTLSVersionedClient(t *testing.T) {
|
||||||
|
certPath := "testing/data/cert.pem"
|
||||||
|
keyPath := "testing/data/key.pem"
|
||||||
|
caPath := "testing/data/ca.pem"
|
||||||
|
endpoint := "https://localhost:4243"
|
||||||
|
client, err := NewVersionnedTLSClient(endpoint, certPath, keyPath, caPath, "1.14")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if client.endpoint != endpoint {
|
||||||
|
t.Errorf("Expected endpoint %s. Got %s.", endpoint, client.endpoint)
|
||||||
|
}
|
||||||
|
if reqVersion := client.requestedAPIVersion.String(); reqVersion != "1.14" {
|
||||||
|
t.Errorf("Wrong requestAPIVersion. Want %q. Got %q.", "1.14", reqVersion)
|
||||||
|
}
|
||||||
|
if client.SkipServerVersionCheck {
|
||||||
|
t.Error("Expected SkipServerVersionCheck to be false, got true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewTLSVersionedClientInvalidCA(t *testing.T) {
|
||||||
|
certPath := "testing/data/cert.pem"
|
||||||
|
keyPath := "testing/data/key.pem"
|
||||||
|
caPath := "testing/data/key.pem"
|
||||||
|
endpoint := "https://localhost:4243"
|
||||||
|
_, err := NewVersionnedTLSClient(endpoint, certPath, keyPath, caPath, "1.14")
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Expected invalid ca at %s", caPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewClientInvalidEndpoint(t *testing.T) {
|
func TestNewClientInvalidEndpoint(t *testing.T) {
|
||||||
cases := []string{
|
cases := []string{
|
||||||
"htp://localhost:3243", "http://localhost:a", "localhost:8080",
|
"htp://localhost:3243", "http://localhost:a", "localhost:8080",
|
||||||
@ -81,6 +136,28 @@ func TestNewClientInvalidEndpoint(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewTLSClient2376(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
endpoint string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{"tcp://localhost:2376", "https"},
|
||||||
|
{"tcp://localhost:2375", "http"},
|
||||||
|
{"tcp://localhost:4000", "http"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
client, err := newTLSClient(tt.endpoint)
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
got := client.endpointURL.Scheme
|
||||||
|
if got != tt.expected {
|
||||||
|
t.Errorf("endpointURL.Scheme: Got %s. Want %s.", got, tt.expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetURL(t *testing.T) {
|
func TestGetURL(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
endpoint string
|
endpoint string
|
||||||
@ -129,6 +206,7 @@ func TestQueryString(t *testing.T) {
|
|||||||
{ListContainersOptions{All: true}, "all=1"},
|
{ListContainersOptions{All: true}, "all=1"},
|
||||||
{ListContainersOptions{Before: "something"}, "before=something"},
|
{ListContainersOptions{Before: "something"}, "before=something"},
|
||||||
{ListContainersOptions{Before: "something", Since: "other"}, "before=something&since=other"},
|
{ListContainersOptions{Before: "something", Since: "other"}, "before=something&since=other"},
|
||||||
|
{ListContainersOptions{Filters: map[string][]string{"status": {"paused", "running"}}}, "filters=%7B%22status%22%3A%5B%22paused%22%2C%22running%22%5D%7D"},
|
||||||
{dumb{X: 10, Y: 10.35000}, "x=10&y=10.35"},
|
{dumb{X: 10, Y: 10.35000}, "x=10&y=10.35"},
|
||||||
{dumb{W: v, X: 10, Y: 10.35000}, f32QueryString},
|
{dumb{W: v, X: 10, Y: 10.35000}, f32QueryString},
|
||||||
{dumb{X: 10, Y: 10.35000, Z: 10}, "x=10&y=10.35&zee=10"},
|
{dumb{X: 10, Y: 10.35000, Z: 10}, "x=10&y=10.35&zee=10"},
|
||||||
@ -147,7 +225,7 @@ func TestQueryString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewApiVersionFailures(t *testing.T) {
|
func TestNewAPIVersionFailures(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
input string
|
input string
|
||||||
expectedError string
|
expectedError string
|
||||||
@ -156,17 +234,17 @@ func TestNewApiVersionFailures(t *testing.T) {
|
|||||||
{"1.0-beta", `Unable to parse version "1.0-beta": "0-beta" is not an integer`},
|
{"1.0-beta", `Unable to parse version "1.0-beta": "0-beta" is not an integer`},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
v, err := NewApiVersion(tt.input)
|
v, err := NewAPIVersion(tt.input)
|
||||||
if v != nil {
|
if v != nil {
|
||||||
t.Errorf("Expected <nil> version, got %v.", v)
|
t.Errorf("Expected <nil> version, got %v.", v)
|
||||||
}
|
}
|
||||||
if err.Error() != tt.expectedError {
|
if err.Error() != tt.expectedError {
|
||||||
t.Errorf("NewApiVersion(%q): wrong error. Want %q. Got %q", tt.input, tt.expectedError, err.Error())
|
t.Errorf("NewAPIVersion(%q): wrong error. Want %q. Got %q", tt.input, tt.expectedError, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestApiVersions(t *testing.T) {
|
func TestAPIVersions(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
a string
|
a string
|
||||||
b string
|
b string
|
||||||
@ -192,8 +270,8 @@ func TestApiVersions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
a, _ := NewApiVersion(tt.a)
|
a, _ := NewAPIVersion(tt.a)
|
||||||
b, _ := NewApiVersion(tt.b)
|
b, _ := NewAPIVersion(tt.b)
|
||||||
|
|
||||||
if tt.expectedALessThanB && !a.LessThan(b) {
|
if tt.expectedALessThanB && !a.LessThan(b) {
|
||||||
t.Errorf("Expected %#v < %#v", a, b)
|
t.Errorf("Expected %#v < %#v", a, b)
|
||||||
|
65
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/container.go
generated
vendored
65
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/container.go
generated
vendored
@ -18,15 +18,17 @@ import (
|
|||||||
|
|
||||||
// ListContainersOptions specify parameters to the ListContainers function.
|
// ListContainersOptions specify parameters to the ListContainers function.
|
||||||
//
|
//
|
||||||
// See http://goo.gl/XqtcyU for more details.
|
// See http://goo.gl/6Y4Gz7 for more details.
|
||||||
type ListContainersOptions struct {
|
type ListContainersOptions struct {
|
||||||
All bool
|
All bool
|
||||||
Size bool
|
Size bool
|
||||||
Limit int
|
Limit int
|
||||||
Since string
|
Since string
|
||||||
Before string
|
Before string
|
||||||
|
Filters map[string][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// APIPort is a type that represents a port mapping returned by the Docker API
|
||||||
type APIPort struct {
|
type APIPort struct {
|
||||||
PrivatePort int64 `json:"PrivatePort,omitempty" yaml:"PrivatePort,omitempty"`
|
PrivatePort int64 `json:"PrivatePort,omitempty" yaml:"PrivatePort,omitempty"`
|
||||||
PublicPort int64 `json:"PublicPort,omitempty" yaml:"PublicPort,omitempty"`
|
PublicPort int64 `json:"PublicPort,omitempty" yaml:"PublicPort,omitempty"`
|
||||||
@ -51,7 +53,7 @@ type APIContainers struct {
|
|||||||
|
|
||||||
// ListContainers returns a slice of containers matching the given criteria.
|
// ListContainers returns a slice of containers matching the given criteria.
|
||||||
//
|
//
|
||||||
// See http://goo.gl/XqtcyU for more details.
|
// See http://goo.gl/6Y4Gz7 for more details.
|
||||||
func (c *Client) ListContainers(opts ListContainersOptions) ([]APIContainers, error) {
|
func (c *Client) ListContainers(opts ListContainersOptions) ([]APIContainers, error) {
|
||||||
path := "/containers/json?" + queryString(opts)
|
path := "/containers/json?" + queryString(opts)
|
||||||
body, _, err := c.do("GET", path, nil)
|
body, _, err := c.do("GET", path, nil)
|
||||||
@ -88,8 +90,10 @@ func (p Port) Proto() string {
|
|||||||
type State struct {
|
type State struct {
|
||||||
Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
|
Running bool `json:"Running,omitempty" yaml:"Running,omitempty"`
|
||||||
Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"`
|
Paused bool `json:"Paused,omitempty" yaml:"Paused,omitempty"`
|
||||||
|
OOMKilled bool `json:"OOMKilled,omitempty" yaml:"OOMKilled,omitempty"`
|
||||||
Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"`
|
Pid int `json:"Pid,omitempty" yaml:"Pid,omitempty"`
|
||||||
ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
|
ExitCode int `json:"ExitCode,omitempty" yaml:"ExitCode,omitempty"`
|
||||||
|
Error string `json:"Error,omitempty" yaml:"Error,omitempty"`
|
||||||
StartedAt time.Time `json:"StartedAt,omitempty" yaml:"StartedAt,omitempty"`
|
StartedAt time.Time `json:"StartedAt,omitempty" yaml:"StartedAt,omitempty"`
|
||||||
FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"`
|
FinishedAt time.Time `json:"FinishedAt,omitempty" yaml:"FinishedAt,omitempty"`
|
||||||
}
|
}
|
||||||
@ -105,13 +109,18 @@ func (s *State) String() string {
|
|||||||
return fmt.Sprintf("Exit %d", s.ExitCode)
|
return fmt.Sprintf("Exit %d", s.ExitCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PortBinding represents the host/container port mapping as returned in the
|
||||||
|
// `docker inspect` json
|
||||||
type PortBinding struct {
|
type PortBinding struct {
|
||||||
HostIp string `json:"HostIP,omitempty" yaml:"HostIP,omitempty"`
|
HostIP string `json:"HostIP,omitempty" yaml:"HostIP,omitempty"`
|
||||||
HostPort string `json:"HostPort,omitempty" yaml:"HostPort,omitempty"`
|
HostPort string `json:"HostPort,omitempty" yaml:"HostPort,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PortMapping represents a deprecated field in the `docker inspect` output,
|
||||||
|
// and its value as found in NetworkSettings should always be nil
|
||||||
type PortMapping map[string]string
|
type PortMapping map[string]string
|
||||||
|
|
||||||
|
// NetworkSettings contains network-related information about a container
|
||||||
type NetworkSettings struct {
|
type NetworkSettings struct {
|
||||||
IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
|
IPAddress string `json:"IPAddress,omitempty" yaml:"IPAddress,omitempty"`
|
||||||
IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty"`
|
IPPrefixLen int `json:"IPPrefixLen,omitempty" yaml:"IPPrefixLen,omitempty"`
|
||||||
@ -121,6 +130,8 @@ type NetworkSettings struct {
|
|||||||
Ports map[Port][]PortBinding `json:"Ports,omitempty" yaml:"Ports,omitempty"`
|
Ports map[Port][]PortBinding `json:"Ports,omitempty" yaml:"Ports,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PortMappingAPI translates the port mappings as contained in NetworkSettings
|
||||||
|
// into the format in which they would appear when returned by the API
|
||||||
func (settings *NetworkSettings) PortMappingAPI() []APIPort {
|
func (settings *NetworkSettings) PortMappingAPI() []APIPort {
|
||||||
var mapping []APIPort
|
var mapping []APIPort
|
||||||
for port, bindings := range settings.Ports {
|
for port, bindings := range settings.Ports {
|
||||||
@ -139,7 +150,7 @@ func (settings *NetworkSettings) PortMappingAPI() []APIPort {
|
|||||||
PrivatePort: int64(p),
|
PrivatePort: int64(p),
|
||||||
PublicPort: int64(h),
|
PublicPort: int64(h),
|
||||||
Type: port.Proto(),
|
Type: port.Proto(),
|
||||||
IP: binding.HostIp,
|
IP: binding.HostIP,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,14 +165,17 @@ func parsePort(rawPort string) (int, error) {
|
|||||||
return int(port), nil
|
return int(port), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config is the list of configuration options used when creating a container.
|
||||||
|
// Config does not the options that are specific to starting a container on a
|
||||||
|
// given host. Those are contained in HostConfig
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Hostname string `json:"Hostname,omitempty" yaml:"Hostname,omitempty"`
|
Hostname string `json:"Hostname,omitempty" yaml:"Hostname,omitempty"`
|
||||||
Domainname string `json:"Domainname,omitempty" yaml:"Domainname,omitempty"`
|
Domainname string `json:"Domainname,omitempty" yaml:"Domainname,omitempty"`
|
||||||
User string `json:"User,omitempty" yaml:"User,omitempty"`
|
User string `json:"User,omitempty" yaml:"User,omitempty"`
|
||||||
Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
|
Memory int64 `json:"Memory,omitempty" yaml:"Memory,omitempty"`
|
||||||
MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty"`
|
MemorySwap int64 `json:"MemorySwap,omitempty" yaml:"MemorySwap,omitempty"`
|
||||||
CpuShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty"`
|
CPUShares int64 `json:"CpuShares,omitempty" yaml:"CpuShares,omitempty"`
|
||||||
CpuSet string `json:"CpuSet,omitempty" yaml:"CpuSet,omitempty"`
|
CPUSet string `json:"Cpuset,omitempty" yaml:"Cpuset,omitempty"`
|
||||||
AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty"`
|
AttachStdin bool `json:"AttachStdin,omitempty" yaml:"AttachStdin,omitempty"`
|
||||||
AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty"`
|
AttachStdout bool `json:"AttachStdout,omitempty" yaml:"AttachStdout,omitempty"`
|
||||||
AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty"`
|
AttachStderr bool `json:"AttachStderr,omitempty" yaml:"AttachStderr,omitempty"`
|
||||||
@ -172,7 +186,7 @@ type Config struct {
|
|||||||
StdinOnce bool `json:"StdinOnce,omitempty" yaml:"StdinOnce,omitempty"`
|
StdinOnce bool `json:"StdinOnce,omitempty" yaml:"StdinOnce,omitempty"`
|
||||||
Env []string `json:"Env,omitempty" yaml:"Env,omitempty"`
|
Env []string `json:"Env,omitempty" yaml:"Env,omitempty"`
|
||||||
Cmd []string `json:"Cmd,omitempty" yaml:"Cmd,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
|
DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty"` // For Docker API v1.9 and below only
|
||||||
Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
|
Image string `json:"Image,omitempty" yaml:"Image,omitempty"`
|
||||||
Volumes map[string]struct{} `json:"Volumes,omitempty" yaml:"Volumes,omitempty"`
|
Volumes map[string]struct{} `json:"Volumes,omitempty" yaml:"Volumes,omitempty"`
|
||||||
VolumesFrom string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
|
VolumesFrom string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
|
||||||
@ -181,6 +195,8 @@ type Config struct {
|
|||||||
NetworkDisabled bool `json:"NetworkDisabled,omitempty" yaml:"NetworkDisabled,omitempty"`
|
NetworkDisabled bool `json:"NetworkDisabled,omitempty" yaml:"NetworkDisabled,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Container is the type encompasing everything about a container - its config,
|
||||||
|
// hostconfig, etc.
|
||||||
type Container struct {
|
type Container struct {
|
||||||
ID string `json:"Id" yaml:"Id"`
|
ID string `json:"Id" yaml:"Id"`
|
||||||
|
|
||||||
@ -249,10 +265,11 @@ func (c *Client) ContainerChanges(id string) ([]Change, error) {
|
|||||||
|
|
||||||
// CreateContainerOptions specify parameters to the CreateContainer function.
|
// CreateContainerOptions specify parameters to the CreateContainer function.
|
||||||
//
|
//
|
||||||
// See http://goo.gl/mErxNp for more details.
|
// See http://goo.gl/2xxQQK for more details.
|
||||||
type CreateContainerOptions struct {
|
type CreateContainerOptions struct {
|
||||||
Name string
|
Name string
|
||||||
Config *Config `qs:"-"`
|
Config *Config `qs:"-"`
|
||||||
|
HostConfig *HostConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateContainer creates a new container, returning the container instance,
|
// CreateContainer creates a new container, returning the container instance,
|
||||||
@ -261,7 +278,14 @@ type CreateContainerOptions struct {
|
|||||||
// See http://goo.gl/mErxNp for more details.
|
// See http://goo.gl/mErxNp for more details.
|
||||||
func (c *Client) CreateContainer(opts CreateContainerOptions) (*Container, error) {
|
func (c *Client) CreateContainer(opts CreateContainerOptions) (*Container, error) {
|
||||||
path := "/containers/create?" + queryString(opts)
|
path := "/containers/create?" + queryString(opts)
|
||||||
body, status, err := c.do("POST", path, opts.Config)
|
body, status, err := c.do("POST", path, struct {
|
||||||
|
*Config
|
||||||
|
HostConfig *HostConfig `json:"HostConfig,omitempty" yaml:"HostConfig,omitempty"`
|
||||||
|
}{
|
||||||
|
opts.Config,
|
||||||
|
opts.HostConfig,
|
||||||
|
})
|
||||||
|
|
||||||
if status == http.StatusNotFound {
|
if status == http.StatusNotFound {
|
||||||
return nil, ErrNoSuchImage
|
return nil, ErrNoSuchImage
|
||||||
}
|
}
|
||||||
@ -279,6 +303,8 @@ func (c *Client) CreateContainer(opts CreateContainerOptions) (*Container, error
|
|||||||
return &container, nil
|
return &container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KeyValuePair is a type for generic key/value pairs as used in the Lxc
|
||||||
|
// configuration
|
||||||
type KeyValuePair struct {
|
type KeyValuePair struct {
|
||||||
Key string `json:"Key,omitempty" yaml:"Key,omitempty"`
|
Key string `json:"Key,omitempty" yaml:"Key,omitempty"`
|
||||||
Value string `json:"Value,omitempty" yaml:"Value,omitempty"`
|
Value string `json:"Value,omitempty" yaml:"Value,omitempty"`
|
||||||
@ -315,6 +341,8 @@ func NeverRestart() RestartPolicy {
|
|||||||
return RestartPolicy{Name: "no"}
|
return RestartPolicy{Name: "no"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HostConfig contains the container options related to starting a container on
|
||||||
|
// a given host
|
||||||
type HostConfig struct {
|
type HostConfig struct {
|
||||||
Binds []string `json:"Binds,omitempty" yaml:"Binds,omitempty"`
|
Binds []string `json:"Binds,omitempty" yaml:"Binds,omitempty"`
|
||||||
CapAdd []string `json:"CapAdd,omitempty" yaml:"CapAdd,omitempty"`
|
CapAdd []string `json:"CapAdd,omitempty" yaml:"CapAdd,omitempty"`
|
||||||
@ -325,8 +353,9 @@ type HostConfig struct {
|
|||||||
PortBindings map[Port][]PortBinding `json:"PortBindings,omitempty" yaml:"PortBindings,omitempty"`
|
PortBindings map[Port][]PortBinding `json:"PortBindings,omitempty" yaml:"PortBindings,omitempty"`
|
||||||
Links []string `json:"Links,omitempty" yaml:"Links,omitempty"`
|
Links []string `json:"Links,omitempty" yaml:"Links,omitempty"`
|
||||||
PublishAllPorts bool `json:"PublishAllPorts,omitempty" yaml:"PublishAllPorts,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
|
DNS []string `json:"Dns,omitempty" yaml:"Dns,omitempty"` // For Docker API v1.10 and above only
|
||||||
DnsSearch []string `json:"DnsSearch,omitempty" yaml:"DnsSearch,omitempty"`
|
DNSSearch []string `json:"DnsSearch,omitempty" yaml:"DnsSearch,omitempty"`
|
||||||
|
ExtraHosts []string `json:"ExtraHosts,omitempty" yaml:"ExtraHosts,omitempty"`
|
||||||
VolumesFrom []string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
|
VolumesFrom []string `json:"VolumesFrom,omitempty" yaml:"VolumesFrom,omitempty"`
|
||||||
NetworkMode string `json:"NetworkMode,omitempty" yaml:"NetworkMode,omitempty"`
|
NetworkMode string `json:"NetworkMode,omitempty" yaml:"NetworkMode,omitempty"`
|
||||||
RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty"`
|
RestartPolicy RestartPolicy `json:"RestartPolicy,omitempty" yaml:"RestartPolicy,omitempty"`
|
||||||
|
31
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/container_test.go
generated
vendored
31
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/container_test.go
generated
vendored
@ -102,6 +102,14 @@ func TestListContainersParams(t *testing.T) {
|
|||||||
ListContainersOptions{All: true, Limit: 10, Since: "adf9983", Before: "abdeef"},
|
ListContainersOptions{All: true, Limit: 10, Since: "adf9983", Before: "abdeef"},
|
||||||
map[string][]string{"all": {"1"}, "limit": {"10"}, "since": {"adf9983"}, "before": {"abdeef"}},
|
map[string][]string{"all": {"1"}, "limit": {"10"}, "since": {"adf9983"}, "before": {"abdeef"}},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
ListContainersOptions{Filters: map[string][]string{"status": {"paused", "running"}}},
|
||||||
|
map[string][]string{"filters": {"{\"status\":[\"paused\",\"running\"]}"}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ListContainersOptions{All: true, Filters: map[string][]string{"exited": {"0"}, "status": {"exited"}}},
|
||||||
|
map[string][]string{"all": {"1"}, "filters": {"{\"exited\":[\"0\"],\"status\":[\"exited\"]}"}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
fakeRT := &FakeRoundTripper{message: "[]", status: http.StatusOK}
|
fakeRT := &FakeRoundTripper{message: "[]", status: http.StatusOK}
|
||||||
client := newTestClient(fakeRT)
|
client := newTestClient(fakeRT)
|
||||||
@ -440,6 +448,27 @@ func TestCreateContainerImageNotFound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreateContainerWithHostConfig(t *testing.T) {
|
||||||
|
fakeRT := &FakeRoundTripper{message: "{}", status: http.StatusOK}
|
||||||
|
client := newTestClient(fakeRT)
|
||||||
|
config := Config{}
|
||||||
|
hostConfig := HostConfig{PublishAllPorts: true}
|
||||||
|
opts := CreateContainerOptions{Name: "TestCreateContainerWithHostConfig", Config: &config, HostConfig: &hostConfig}
|
||||||
|
_, err := client.CreateContainer(opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
req := fakeRT.requests[0]
|
||||||
|
var gotBody map[string]interface{}
|
||||||
|
err = json.NewDecoder(req.Body).Decode(&gotBody)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if _, ok := gotBody["HostConfig"]; !ok {
|
||||||
|
t.Errorf("CreateContainer: wrong body. HostConfig was not serialized")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestStartContainer(t *testing.T) {
|
func TestStartContainer(t *testing.T) {
|
||||||
fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
|
fakeRT := &FakeRoundTripper{message: "", status: http.StatusOK}
|
||||||
client := newTestClient(fakeRT)
|
client := newTestClient(fakeRT)
|
||||||
@ -1251,7 +1280,7 @@ func TestLogsNoContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNoSuchContainerError(t *testing.T) {
|
func TestNoSuchContainerError(t *testing.T) {
|
||||||
var err error = &NoSuchContainer{ID: "i345"}
|
var err = &NoSuchContainer{ID: "i345"}
|
||||||
expected := "No such container: i345"
|
expected := "No such container: i345"
|
||||||
if got := err.Error(); got != expected {
|
if got := err.Error(); got != expected {
|
||||||
t.Errorf("NoSuchContainer: wrong message. Want %q. Got %q.", expected, got)
|
t.Errorf("NoSuchContainer: wrong message. Want %q. Got %q.", expected, got)
|
||||||
|
41
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/event.go
generated
vendored
41
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/event.go
generated
vendored
@ -5,6 +5,7 @@
|
|||||||
package docker
|
package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -49,6 +50,11 @@ var (
|
|||||||
// ErrListenerAlreadyExists is the error returned when the listerner already
|
// ErrListenerAlreadyExists is the error returned when the listerner already
|
||||||
// exists.
|
// exists.
|
||||||
ErrListenerAlreadyExists = errors.New("listener already exists for docker events")
|
ErrListenerAlreadyExists = errors.New("listener already exists for docker events")
|
||||||
|
|
||||||
|
// EOFEvent is sent when the event listener receives an EOF error.
|
||||||
|
EOFEvent = &APIEvents{
|
||||||
|
Status: "EOF",
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddEventListener adds a new listener to container events in the Docker API.
|
// AddEventListener adds a new listener to container events in the Docker API.
|
||||||
@ -111,6 +117,16 @@ func (eventState *eventMonitoringState) removeListener(listener chan<- *APIEvent
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (eventState *eventMonitoringState) closeListeners() {
|
||||||
|
eventState.Lock()
|
||||||
|
defer eventState.Unlock()
|
||||||
|
for _, l := range eventState.listeners {
|
||||||
|
close(l)
|
||||||
|
eventState.Add(-1)
|
||||||
|
}
|
||||||
|
eventState.listeners = nil
|
||||||
|
}
|
||||||
|
|
||||||
func listenerExists(a chan<- *APIEvents, list *[]chan<- *APIEvents) bool {
|
func listenerExists(a chan<- *APIEvents, list *[]chan<- *APIEvents) bool {
|
||||||
for _, b := range *list {
|
for _, b := range *list {
|
||||||
if b == a {
|
if b == a {
|
||||||
@ -152,7 +168,7 @@ func (eventState *eventMonitoringState) monitorEvents(c *Client) {
|
|||||||
time.Sleep(10 * time.Millisecond)
|
time.Sleep(10 * time.Millisecond)
|
||||||
}
|
}
|
||||||
if err = eventState.connectWithRetry(c); err != nil {
|
if err = eventState.connectWithRetry(c); err != nil {
|
||||||
eventState.terminate(err)
|
eventState.terminate()
|
||||||
}
|
}
|
||||||
for eventState.isEnabled() {
|
for eventState.isEnabled() {
|
||||||
timeout := time.After(100 * time.Millisecond)
|
timeout := time.After(100 * time.Millisecond)
|
||||||
@ -161,11 +177,16 @@ func (eventState *eventMonitoringState) monitorEvents(c *Client) {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if ev == EOFEvent {
|
||||||
|
eventState.closeListeners()
|
||||||
|
eventState.terminate()
|
||||||
|
return
|
||||||
|
}
|
||||||
go eventState.sendEvent(ev)
|
go eventState.sendEvent(ev)
|
||||||
go eventState.updateLastSeen(ev)
|
go eventState.updateLastSeen(ev)
|
||||||
case err = <-eventState.errC:
|
case err = <-eventState.errC:
|
||||||
if err == ErrNoListeners {
|
if err == ErrNoListeners {
|
||||||
eventState.terminate(nil)
|
eventState.terminate()
|
||||||
return
|
return
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
defer func() { go eventState.monitorEvents(c) }()
|
defer func() { go eventState.monitorEvents(c) }()
|
||||||
@ -225,7 +246,7 @@ func (eventState *eventMonitoringState) updateLastSeen(e *APIEvents) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (eventState *eventMonitoringState) terminate(err error) {
|
func (eventState *eventMonitoringState) terminate() {
|
||||||
eventState.disableEventMonitoring()
|
eventState.disableEventMonitoring()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +261,13 @@ func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan
|
|||||||
protocol = "tcp"
|
protocol = "tcp"
|
||||||
address = c.endpointURL.Host
|
address = c.endpointURL.Host
|
||||||
}
|
}
|
||||||
dial, err := net.Dial(protocol, address)
|
var dial net.Conn
|
||||||
|
var err error
|
||||||
|
if c.TLSConfig == nil {
|
||||||
|
dial, err = net.Dial(protocol, address)
|
||||||
|
} else {
|
||||||
|
dial, err = tls.Dial(protocol, address, c.TLSConfig)
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -261,6 +288,10 @@ func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan
|
|||||||
var event APIEvents
|
var event APIEvents
|
||||||
if err = decoder.Decode(&event); err != nil {
|
if err = decoder.Decode(&event); err != nil {
|
||||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||||
|
if c.eventMonitor.isEnabled() {
|
||||||
|
// Signal that we're exiting.
|
||||||
|
eventChan <- EOFEvent
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
errChan <- err
|
errChan <- err
|
||||||
@ -271,7 +302,7 @@ func (c *Client) eventHijack(startTime int64, eventChan chan *APIEvents, errChan
|
|||||||
if !c.eventMonitor.isEnabled() {
|
if !c.eventMonitor.isEnabled() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.eventMonitor.C <- &event
|
eventChan <- &event
|
||||||
}
|
}
|
||||||
}(res, conn)
|
}(res, conn)
|
||||||
return nil
|
return nil
|
||||||
|
44
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/event_test.go
generated
vendored
44
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/event_test.go
generated
vendored
@ -6,7 +6,10 @@ package docker
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"crypto/tls"
|
||||||
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
@ -15,6 +18,39 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestEventListeners(t *testing.T) {
|
func TestEventListeners(t *testing.T) {
|
||||||
|
testEventListeners("TestEventListeners", t, httptest.NewServer, NewClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTLSEventListeners(t *testing.T) {
|
||||||
|
testEventListeners("TestTLSEventListeners", t, func(handler http.Handler) *httptest.Server {
|
||||||
|
server := httptest.NewUnstartedServer(handler)
|
||||||
|
|
||||||
|
cert, err := tls.LoadX509KeyPair("testing/data/server.pem", "testing/data/serverkey.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error loading server key pair: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
caCert, err := ioutil.ReadFile("testing/data/ca.pem")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error loading ca certificate: %s", err)
|
||||||
|
}
|
||||||
|
caPool := x509.NewCertPool()
|
||||||
|
if !caPool.AppendCertsFromPEM(caCert) {
|
||||||
|
t.Fatalf("Could not add ca certificate")
|
||||||
|
}
|
||||||
|
|
||||||
|
server.TLS = &tls.Config{
|
||||||
|
Certificates: []tls.Certificate{cert},
|
||||||
|
RootCAs: caPool,
|
||||||
|
}
|
||||||
|
server.StartTLS()
|
||||||
|
return server
|
||||||
|
}, func(url string) (*Client, error) {
|
||||||
|
return NewTLSClient(url, "testing/data/cert.pem", "testing/data/key.pem", "testing/data/ca.pem")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testEventListeners(testName string, t *testing.T, buildServer func(http.Handler) *httptest.Server, buildClient func(string) (*Client, error)) {
|
||||||
response := `{"status":"create","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
|
response := `{"status":"create","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
|
||||||
{"status":"start","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
|
{"status":"start","id":"dfdf82bd3881","from":"base:latest","time":1374067924}
|
||||||
{"status":"stop","id":"dfdf82bd3881","from":"base:latest","time":1374067966}
|
{"status":"stop","id":"dfdf82bd3881","from":"base:latest","time":1374067966}
|
||||||
@ -22,7 +58,7 @@ func TestEventListeners(t *testing.T) {
|
|||||||
`
|
`
|
||||||
|
|
||||||
var req http.Request
|
var req http.Request
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
server := buildServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
rsc := bufio.NewScanner(strings.NewReader(response))
|
rsc := bufio.NewScanner(strings.NewReader(response))
|
||||||
for rsc.Scan() {
|
for rsc.Scan() {
|
||||||
w.Write([]byte(rsc.Text()))
|
w.Write([]byte(rsc.Text()))
|
||||||
@ -33,7 +69,7 @@ func TestEventListeners(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
defer server.Close()
|
defer server.Close()
|
||||||
|
|
||||||
client, err := NewClient(server.URL)
|
client, err := buildClient(server.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to create client: %s", err)
|
t.Errorf("Failed to create client: %s", err)
|
||||||
}
|
}
|
||||||
@ -53,7 +89,7 @@ func TestEventListeners(t *testing.T) {
|
|||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case msg := <-listener:
|
case msg := <-listener:
|
||||||
t.Logf("Recieved: %s", *msg)
|
t.Logf("Received: %s", *msg)
|
||||||
count++
|
count++
|
||||||
err = checkEvent(count, msg)
|
err = checkEvent(count, msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -63,7 +99,7 @@ func TestEventListeners(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
t.Fatal("TestAddEventListener timed out waiting on events")
|
t.Fatalf("%s timed out waiting on events", testName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
15
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/exec.go
generated
vendored
15
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/exec.go
generated
vendored
@ -50,8 +50,10 @@ type StartExecOptions struct {
|
|||||||
Success chan struct{} `json:"-"`
|
Success chan struct{} `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Exec is the type representing a `docker exec` instance and containing the
|
||||||
|
// instance ID
|
||||||
type Exec struct {
|
type Exec struct {
|
||||||
Id string `json:"Id,omitempty" yaml:"Id,omitempty"`
|
ID string `json:"Id,omitempty" yaml:"Id,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateExec sets up an exec instance in a running container `id`, returning the exec
|
// CreateExec sets up an exec instance in a running container `id`, returning the exec
|
||||||
@ -76,9 +78,9 @@ func (c *Client) CreateExec(opts CreateExecOptions) (*Exec, error) {
|
|||||||
return &exec, nil
|
return &exec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starts a previously set up exec instance id. If opts.Detach is true, it returns
|
// StartExec starts a previously set up exec instance id. If opts.Detach is
|
||||||
// after starting the exec command. Otherwise, it sets up an interactive session
|
// true, it returns after starting the exec command. Otherwise, it sets up an
|
||||||
// with the exec command.
|
// interactive session with the exec command.
|
||||||
//
|
//
|
||||||
// See http://goo.gl/JW8Lxl for more details
|
// See http://goo.gl/JW8Lxl for more details
|
||||||
func (c *Client) StartExec(id string, opts StartExecOptions) error {
|
func (c *Client) StartExec(id string, opts StartExecOptions) error {
|
||||||
@ -102,8 +104,9 @@ func (c *Client) StartExec(id string, opts StartExecOptions) error {
|
|||||||
return c.hijack("POST", path, opts.Success, opts.RawTerminal, opts.InputStream, opts.ErrorStream, opts.OutputStream, opts)
|
return c.hijack("POST", path, opts.Success, opts.RawTerminal, opts.InputStream, opts.ErrorStream, opts.OutputStream, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resizes the tty session used by the exec command id. This API is valid only
|
// ResizeExecTTY resizes the tty session used by the exec command id. This API
|
||||||
// if Tty was specified as part of creating and starting the exec command.
|
// is valid only if Tty was specified as part of creating and starting the exec
|
||||||
|
// command.
|
||||||
//
|
//
|
||||||
// See http://goo.gl/YDSx1f for more details
|
// See http://goo.gl/YDSx1f for more details
|
||||||
func (c *Client) ResizeExecTTY(id string, height, width int) error {
|
func (c *Client) ResizeExecTTY(id string, height, width int) error {
|
||||||
|
26
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/exec_test.go
generated
vendored
26
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/exec_test.go
generated
vendored
@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
func TestExecCreate(t *testing.T) {
|
func TestExecCreate(t *testing.T) {
|
||||||
jsonContainer := `{"Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"}`
|
jsonContainer := `{"Id": "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"}`
|
||||||
var expected struct{ Id string }
|
var expected struct{ ID string }
|
||||||
err := json.Unmarshal([]byte(jsonContainer), &expected)
|
err := json.Unmarshal([]byte(jsonContainer), &expected)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -35,9 +35,9 @@ func TestExecCreate(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
expectedId := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
|
expectedID := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
|
||||||
if execObj.Id != expectedId {
|
if execObj.ID != expectedID {
|
||||||
t.Errorf("ExecCreate: wrong ID. Want %q. Got %q.", expectedId, execObj.Id)
|
t.Errorf("ExecCreate: wrong ID. Want %q. Got %q.", expectedID, execObj.ID)
|
||||||
}
|
}
|
||||||
req := fakeRT.requests[0]
|
req := fakeRT.requests[0]
|
||||||
if req.Method != "POST" {
|
if req.Method != "POST" {
|
||||||
@ -47,7 +47,7 @@ func TestExecCreate(t *testing.T) {
|
|||||||
if gotPath := req.URL.Path; gotPath != expectedURL.Path {
|
if gotPath := req.URL.Path; gotPath != expectedURL.Path {
|
||||||
t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
|
t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
|
||||||
}
|
}
|
||||||
var gotBody struct{ Id string }
|
var gotBody struct{ ID string }
|
||||||
err = json.NewDecoder(req.Body).Decode(&gotBody)
|
err = json.NewDecoder(req.Body).Decode(&gotBody)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -55,13 +55,13 @@ func TestExecCreate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestExecStartDetached(t *testing.T) {
|
func TestExecStartDetached(t *testing.T) {
|
||||||
execId := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
|
execID := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
|
||||||
fakeRT := &FakeRoundTripper{status: http.StatusOK}
|
fakeRT := &FakeRoundTripper{status: http.StatusOK}
|
||||||
client := newTestClient(fakeRT)
|
client := newTestClient(fakeRT)
|
||||||
config := StartExecOptions{
|
config := StartExecOptions{
|
||||||
Detach: true,
|
Detach: true,
|
||||||
}
|
}
|
||||||
err := client.StartExec(execId, config)
|
err := client.StartExec(execID, config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ func TestExecStartDetached(t *testing.T) {
|
|||||||
if req.Method != "POST" {
|
if req.Method != "POST" {
|
||||||
t.Errorf("ExecStart: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
|
t.Errorf("ExecStart: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
|
||||||
}
|
}
|
||||||
expectedURL, _ := url.Parse(client.getURL("/exec/" + execId + "/start"))
|
expectedURL, _ := url.Parse(client.getURL("/exec/" + execID + "/start"))
|
||||||
if gotPath := req.URL.Path; gotPath != expectedURL.Path {
|
if gotPath := req.URL.Path; gotPath != expectedURL.Path {
|
||||||
t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
|
t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ func TestExecStartAndAttach(t *testing.T) {
|
|||||||
client.SkipServerVersionCheck = true
|
client.SkipServerVersionCheck = true
|
||||||
var stdout, stderr bytes.Buffer
|
var stdout, stderr bytes.Buffer
|
||||||
success := make(chan struct{})
|
success := make(chan struct{})
|
||||||
execId := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
|
execID := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
|
||||||
opts := StartExecOptions{
|
opts := StartExecOptions{
|
||||||
OutputStream: &stdout,
|
OutputStream: &stdout,
|
||||||
ErrorStream: &stderr,
|
ErrorStream: &stderr,
|
||||||
@ -105,15 +105,15 @@ func TestExecStartAndAttach(t *testing.T) {
|
|||||||
RawTerminal: true,
|
RawTerminal: true,
|
||||||
Success: success,
|
Success: success,
|
||||||
}
|
}
|
||||||
go client.StartExec(execId, opts)
|
go client.StartExec(execID, opts)
|
||||||
<-success
|
<-success
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExecResize(t *testing.T) {
|
func TestExecResize(t *testing.T) {
|
||||||
execId := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
|
execID := "4fa6e0f0c6786287e131c3852c58a2e01cc697a68231826813597e4994f1d6e2"
|
||||||
fakeRT := &FakeRoundTripper{status: http.StatusOK}
|
fakeRT := &FakeRoundTripper{status: http.StatusOK}
|
||||||
client := newTestClient(fakeRT)
|
client := newTestClient(fakeRT)
|
||||||
err := client.ResizeExecTTY(execId, 10, 20)
|
err := client.ResizeExecTTY(execID, 10, 20)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ func TestExecResize(t *testing.T) {
|
|||||||
if req.Method != "POST" {
|
if req.Method != "POST" {
|
||||||
t.Errorf("ExecStart: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
|
t.Errorf("ExecStart: wrong HTTP method. Want %q. Got %q.", "POST", req.Method)
|
||||||
}
|
}
|
||||||
expectedURL, _ := url.Parse(client.getURL("/exec/" + execId + "/resize?h=10&w=20"))
|
expectedURL, _ := url.Parse(client.getURL("/exec/" + execID + "/resize?h=10&w=20"))
|
||||||
if gotPath := req.URL.RequestURI(); gotPath != expectedURL.RequestURI() {
|
if gotPath := req.URL.RequestURI(); gotPath != expectedURL.RequestURI() {
|
||||||
t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
|
t.Errorf("ExecCreate: Wrong path in request. Want %q. Got %q.", expectedURL.Path, gotPath)
|
||||||
}
|
}
|
||||||
|
113
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/image.go
generated
vendored
113
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/image.go
generated
vendored
@ -25,9 +25,10 @@ type APIImages struct {
|
|||||||
Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"`
|
Created int64 `json:"Created,omitempty" yaml:"Created,omitempty"`
|
||||||
Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
|
Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
|
||||||
VirtualSize int64 `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
|
VirtualSize int64 `json:"VirtualSize,omitempty" yaml:"VirtualSize,omitempty"`
|
||||||
ParentId string `json:"ParentId,omitempty" yaml:"ParentId,omitempty"`
|
ParentID string `json:"ParentId,omitempty" yaml:"ParentId,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Image is the type representing a docker image and its various properties
|
||||||
type Image struct {
|
type Image struct {
|
||||||
ID string `json:"Id" yaml:"Id"`
|
ID string `json:"Id" yaml:"Id"`
|
||||||
Parent string `json:"Parent,omitempty" yaml:"Parent,omitempty"`
|
Parent string `json:"Parent,omitempty" yaml:"Parent,omitempty"`
|
||||||
@ -52,6 +53,8 @@ type ImageHistory struct {
|
|||||||
Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
|
Size int64 `json:"Size,omitempty" yaml:"Size,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ImagePre012 serves the same purpose as the Image type except that it is for
|
||||||
|
// earlier versions of the Docker API (pre-012 to be specific)
|
||||||
type ImagePre012 struct {
|
type ImagePre012 struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Parent string `json:"parent,omitempty"`
|
Parent string `json:"parent,omitempty"`
|
||||||
@ -66,6 +69,14 @@ type ImagePre012 struct {
|
|||||||
Size int64 `json:"size,omitempty"`
|
Size int64 `json:"size,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListImagesOptions specify parameters to the ListImages function.
|
||||||
|
//
|
||||||
|
// See http://goo.gl/2rOLFF for more details.
|
||||||
|
type ListImagesOptions struct {
|
||||||
|
All bool
|
||||||
|
Filters map[string][]string
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// ErrNoSuchImage is the error returned when the image does not exist.
|
// ErrNoSuchImage is the error returned when the image does not exist.
|
||||||
ErrNoSuchImage = errors.New("no such image")
|
ErrNoSuchImage = errors.New("no such image")
|
||||||
@ -77,18 +88,17 @@ var (
|
|||||||
// ErrMissingOutputStream is the error returned when no output stream
|
// ErrMissingOutputStream is the error returned when no output stream
|
||||||
// is provided to some calls, like BuildImage.
|
// is provided to some calls, like BuildImage.
|
||||||
ErrMissingOutputStream = errors.New("missing output stream")
|
ErrMissingOutputStream = errors.New("missing output stream")
|
||||||
|
|
||||||
|
// ErrMultipleContexts is the error returned when both a ContextDir and
|
||||||
|
// InputStream are provided in BuildImageOptions
|
||||||
|
ErrMultipleContexts = errors.New("image build may not be provided BOTH context dir and input stream")
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListImages returns the list of available images in the server.
|
// ListImages returns the list of available images in the server.
|
||||||
//
|
//
|
||||||
// See http://goo.gl/VmcR6v for more details.
|
// See http://goo.gl/2rOLFF for more details.
|
||||||
func (c *Client) ListImages(all bool) ([]APIImages, error) {
|
func (c *Client) ListImages(opts ListImagesOptions) ([]APIImages, error) {
|
||||||
path := "/images/json?all="
|
path := "/images/json?" + queryString(opts)
|
||||||
if all {
|
|
||||||
path += "1"
|
|
||||||
} else {
|
|
||||||
path += "0"
|
|
||||||
}
|
|
||||||
body, _, err := c.do("GET", path, nil)
|
body, _, err := c.do("GET", path, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -146,7 +156,7 @@ func (c *Client) InspectImage(name string) (*Image, error) {
|
|||||||
var image Image
|
var image Image
|
||||||
|
|
||||||
// if the caller elected to skip checking the server's version, assume it's the latest
|
// if the caller elected to skip checking the server's version, assume it's the latest
|
||||||
if c.SkipServerVersionCheck || c.expectedApiVersion.GreaterThanOrEqualTo(apiVersion_1_12) {
|
if c.SkipServerVersionCheck || c.expectedAPIVersion.GreaterThanOrEqualTo(apiVersion1_12) {
|
||||||
err = json.Unmarshal(body, &image)
|
err = json.Unmarshal(body, &image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -194,9 +204,16 @@ type PushImageOptions struct {
|
|||||||
// AuthConfiguration represents authentication options to use in the PushImage
|
// AuthConfiguration represents authentication options to use in the PushImage
|
||||||
// method. It represents the authentication in the Docker index server.
|
// method. It represents the authentication in the Docker index server.
|
||||||
type AuthConfiguration struct {
|
type AuthConfiguration struct {
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Password string `json:"password,omitempty"`
|
Password string `json:"password,omitempty"`
|
||||||
Email string `json:"email,omitempty"`
|
Email string `json:"email,omitempty"`
|
||||||
|
ServerAddress string `json:"serveraddress,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthConfigurations represents authentication options to use for the
|
||||||
|
// PushImage method accommodating the new X-Registry-Config header
|
||||||
|
type AuthConfigurations struct {
|
||||||
|
Configs map[string]AuthConfiguration `json:"configs"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PushImage pushes an image to a remote registry, logging progress to w.
|
// PushImage pushes an image to a remote registry, logging progress to w.
|
||||||
@ -212,12 +229,7 @@ func (c *Client) PushImage(opts PushImageOptions, auth AuthConfiguration) error
|
|||||||
name := opts.Name
|
name := opts.Name
|
||||||
opts.Name = ""
|
opts.Name = ""
|
||||||
path := "/images/" + name + "/push?" + queryString(&opts)
|
path := "/images/" + name + "/push?" + queryString(&opts)
|
||||||
var headers = make(map[string]string)
|
headers := headersWithAuth(auth)
|
||||||
var buf bytes.Buffer
|
|
||||||
json.NewEncoder(&buf).Encode(auth)
|
|
||||||
|
|
||||||
headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())
|
|
||||||
|
|
||||||
return c.stream("POST", path, true, opts.RawJSONStream, headers, nil, opts.OutputStream, nil)
|
return c.stream("POST", path, true, opts.RawJSONStream, headers, nil, opts.OutputStream, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,11 +253,7 @@ func (c *Client) PullImage(opts PullImageOptions, auth AuthConfiguration) error
|
|||||||
return ErrNoSuchImage
|
return ErrNoSuchImage
|
||||||
}
|
}
|
||||||
|
|
||||||
var headers = make(map[string]string)
|
headers := headersWithAuth(auth)
|
||||||
var buf bytes.Buffer
|
|
||||||
json.NewEncoder(&buf).Encode(auth)
|
|
||||||
headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())
|
|
||||||
|
|
||||||
return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream)
|
return c.createImage(queryString(&opts), headers, nil, opts.OutputStream, opts.RawJSONStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,15 +332,18 @@ func (c *Client) ImportImage(opts ImportImageOptions) error {
|
|||||||
// For more details about the Docker building process, see
|
// For more details about the Docker building process, see
|
||||||
// http://goo.gl/tlPXPu.
|
// http://goo.gl/tlPXPu.
|
||||||
type BuildImageOptions struct {
|
type BuildImageOptions struct {
|
||||||
Name string `qs:"t"`
|
Name string `qs:"t"`
|
||||||
NoCache bool `qs:"nocache"`
|
NoCache bool `qs:"nocache"`
|
||||||
SuppressOutput bool `qs:"q"`
|
SuppressOutput bool `qs:"q"`
|
||||||
RmTmpContainer bool `qs:"rm"`
|
RmTmpContainer bool `qs:"rm"`
|
||||||
ForceRmTmpContainer bool `qs:"forcerm"`
|
ForceRmTmpContainer bool `qs:"forcerm"`
|
||||||
InputStream io.Reader `qs:"-"`
|
InputStream io.Reader `qs:"-"`
|
||||||
OutputStream io.Writer `qs:"-"`
|
OutputStream io.Writer `qs:"-"`
|
||||||
RawJSONStream bool `qs:"-"`
|
RawJSONStream bool `qs:"-"`
|
||||||
Remote string `qs:"remote"`
|
Remote string `qs:"remote"`
|
||||||
|
Auth AuthConfiguration `qs:"-"` // for older docker X-Registry-Auth header
|
||||||
|
AuthConfigs AuthConfigurations `qs:"-"` // for newer docker X-Registry-Config header
|
||||||
|
ContextDir string `qs:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildImage builds an image from a tarball's url or a Dockerfile in the input
|
// BuildImage builds an image from a tarball's url or a Dockerfile in the input
|
||||||
@ -343,15 +354,26 @@ func (c *Client) BuildImage(opts BuildImageOptions) error {
|
|||||||
if opts.OutputStream == nil {
|
if opts.OutputStream == nil {
|
||||||
return ErrMissingOutputStream
|
return ErrMissingOutputStream
|
||||||
}
|
}
|
||||||
var headers map[string]string
|
var headers = headersWithAuth(opts.Auth, opts.AuthConfigs)
|
||||||
|
|
||||||
if opts.Remote != "" && opts.Name == "" {
|
if opts.Remote != "" && opts.Name == "" {
|
||||||
opts.Name = opts.Remote
|
opts.Name = opts.Remote
|
||||||
}
|
}
|
||||||
if opts.InputStream != nil {
|
if opts.InputStream != nil || opts.ContextDir != "" {
|
||||||
headers = map[string]string{"Content-Type": "application/tar"}
|
headers["Content-Type"] = "application/tar"
|
||||||
} else if opts.Remote == "" {
|
} else if opts.Remote == "" {
|
||||||
return ErrMissingRepo
|
return ErrMissingRepo
|
||||||
}
|
}
|
||||||
|
if opts.ContextDir != "" {
|
||||||
|
if opts.InputStream != nil {
|
||||||
|
return ErrMultipleContexts
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
if opts.InputStream, err = createTarStream(opts.ContextDir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return c.stream("POST", fmt.Sprintf("/build?%s",
|
return c.stream("POST", fmt.Sprintf("/build?%s",
|
||||||
queryString(&opts)), true, opts.RawJSONStream, headers, opts.InputStream, opts.OutputStream, nil)
|
queryString(&opts)), true, opts.RawJSONStream, headers, opts.InputStream, opts.OutputStream, nil)
|
||||||
}
|
}
|
||||||
@ -389,6 +411,25 @@ func isURL(u string) bool {
|
|||||||
return p.Scheme == "http" || p.Scheme == "https"
|
return p.Scheme == "http" || p.Scheme == "https"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func headersWithAuth(auths ...interface{}) map[string]string {
|
||||||
|
var headers = make(map[string]string)
|
||||||
|
|
||||||
|
for _, auth := range auths {
|
||||||
|
switch auth.(type) {
|
||||||
|
case AuthConfiguration:
|
||||||
|
var buf bytes.Buffer
|
||||||
|
json.NewEncoder(&buf).Encode(auth)
|
||||||
|
headers["X-Registry-Auth"] = base64.URLEncoding.EncodeToString(buf.Bytes())
|
||||||
|
case AuthConfigurations:
|
||||||
|
var buf bytes.Buffer
|
||||||
|
json.NewEncoder(&buf).Encode(auth)
|
||||||
|
headers["X-Registry-Config"] = base64.URLEncoding.EncodeToString(buf.Bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers
|
||||||
|
}
|
||||||
|
|
||||||
// APIImageSearch reflect the result of a search on the dockerHub
|
// APIImageSearch reflect the result of a search on the dockerHub
|
||||||
//
|
//
|
||||||
// See http://goo.gl/xI5lLZ for more details.
|
// See http://goo.gl/xI5lLZ for more details.
|
||||||
|
31
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/image_test.go
generated
vendored
31
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/image_test.go
generated
vendored
@ -88,7 +88,7 @@ func TestListImages(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
client := newTestClient(&FakeRoundTripper{message: body, status: http.StatusOK})
|
client := newTestClient(&FakeRoundTripper{message: body, status: http.StatusOK})
|
||||||
images, err := client.ListImages(false)
|
images, err := client.ListImages(ListImagesOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -100,25 +100,42 @@ func TestListImages(t *testing.T) {
|
|||||||
func TestListImagesParameters(t *testing.T) {
|
func TestListImagesParameters(t *testing.T) {
|
||||||
fakeRT := &FakeRoundTripper{message: "null", status: http.StatusOK}
|
fakeRT := &FakeRoundTripper{message: "null", status: http.StatusOK}
|
||||||
client := newTestClient(fakeRT)
|
client := newTestClient(fakeRT)
|
||||||
_, err := client.ListImages(false)
|
_, err := client.ListImages(ListImagesOptions{All: false})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
req := fakeRT.requests[0]
|
req := fakeRT.requests[0]
|
||||||
if req.Method != "GET" {
|
if req.Method != "GET" {
|
||||||
t.Errorf("ListImages(false: Wrong HTTP method. Want GET. Got %s.", req.Method)
|
t.Errorf("ListImages({All: false}: Wrong HTTP method. Want GET. Got %s.", req.Method)
|
||||||
}
|
}
|
||||||
if all := req.URL.Query().Get("all"); all != "0" {
|
if all := req.URL.Query().Get("all"); all != "0" && all != "" {
|
||||||
t.Errorf("ListImages(false): Wrong parameter. Want all=0. Got all=%s", all)
|
t.Errorf("ListImages({All: false}): Wrong parameter. Want all=0 or not present at all. Got all=%s", all)
|
||||||
}
|
}
|
||||||
fakeRT.Reset()
|
fakeRT.Reset()
|
||||||
_, err = client.ListImages(true)
|
_, err = client.ListImages(ListImagesOptions{All: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
req = fakeRT.requests[0]
|
req = fakeRT.requests[0]
|
||||||
if all := req.URL.Query().Get("all"); all != "1" {
|
if all := req.URL.Query().Get("all"); all != "1" {
|
||||||
t.Errorf("ListImages(true): Wrong parameter. Want all=1. Got all=%s", all)
|
t.Errorf("ListImages({All: true}): Wrong parameter. Want all=1. Got all=%s", all)
|
||||||
|
}
|
||||||
|
fakeRT.Reset()
|
||||||
|
_, err = client.ListImages(ListImagesOptions{Filters: map[string][]string{
|
||||||
|
"dangling": {"true"},
|
||||||
|
}})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
req = fakeRT.requests[0]
|
||||||
|
body := req.URL.Query().Get("filters")
|
||||||
|
var filters map[string][]string
|
||||||
|
err = json.Unmarshal([]byte(body), &filters)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if len(filters["dangling"]) != 1 || filters["dangling"][0] != "true" {
|
||||||
|
t.Errorf("ListImages(dangling=[true]): Wrong filter map. Want dangling=[true], got dangling=%v", filters["dangling"])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
99
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/tar.go
generated
vendored
Normal file
99
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/tar.go
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// 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 (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/docker/docker/pkg/archive"
|
||||||
|
"github.com/docker/docker/pkg/fileutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func createTarStream(srcPath string) (io.ReadCloser, error) {
|
||||||
|
excludes, err := parseDockerignore(srcPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := validateContextDirectory(srcPath, excludes); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tarOpts := &archive.TarOptions{
|
||||||
|
Excludes: excludes,
|
||||||
|
Compression: archive.Uncompressed,
|
||||||
|
NoLchown: true,
|
||||||
|
}
|
||||||
|
return archive.TarWithOptions(srcPath, tarOpts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// validateContextDirectory checks if all the contents of the directory
|
||||||
|
// can be read and returns an error if some files can't be read.
|
||||||
|
// Symlinks which point to non-existing files don't trigger an error
|
||||||
|
func validateContextDirectory(srcPath string, excludes []string) error {
|
||||||
|
return filepath.Walk(filepath.Join(srcPath, "."), func(filePath string, f os.FileInfo, err error) error {
|
||||||
|
// skip this directory/file if it's not in the path, it won't get added to the context
|
||||||
|
if relFilePath, err := filepath.Rel(srcPath, filePath); err != nil {
|
||||||
|
return err
|
||||||
|
} else if skip, err := fileutils.Matches(relFilePath, excludes); err != nil {
|
||||||
|
return err
|
||||||
|
} else if skip {
|
||||||
|
if f.IsDir() {
|
||||||
|
return filepath.SkipDir
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
if os.IsPermission(err) {
|
||||||
|
return fmt.Errorf("can't stat '%s'", filePath)
|
||||||
|
}
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip checking if symlinks point to non-existing files, such symlinks can be useful
|
||||||
|
// also skip named pipes, because they hanging on open
|
||||||
|
if f.Mode()&(os.ModeSymlink|os.ModeNamedPipe) != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !f.IsDir() {
|
||||||
|
currentFile, err := os.Open(filePath)
|
||||||
|
if err != nil && os.IsPermission(err) {
|
||||||
|
return fmt.Errorf("no permission to read from '%s'", filePath)
|
||||||
|
}
|
||||||
|
currentFile.Close()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseDockerignore(root string) ([]string, error) {
|
||||||
|
var excludes []string
|
||||||
|
ignore, err := ioutil.ReadFile(path.Join(root, ".dockerignore"))
|
||||||
|
if err != nil && !os.IsNotExist(err) {
|
||||||
|
return excludes, fmt.Errorf("error reading .dockerignore: '%s'", err)
|
||||||
|
}
|
||||||
|
for _, pattern := range strings.Split(string(ignore), "\n") {
|
||||||
|
matches, err := filepath.Match(pattern, "Dockerfile")
|
||||||
|
if err != nil {
|
||||||
|
return excludes, fmt.Errorf("bad .dockerignore pattern: '%s', error: %s", pattern, err)
|
||||||
|
}
|
||||||
|
if matches {
|
||||||
|
return excludes, fmt.Errorf("dockerfile was excluded by .dockerignore pattern '%s'", pattern)
|
||||||
|
}
|
||||||
|
excludes = append(excludes, pattern)
|
||||||
|
}
|
||||||
|
|
||||||
|
return excludes, nil
|
||||||
|
}
|
38
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/bin/fmtpolice
generated
vendored
Normal file
38
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/bin/fmtpolice
generated
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
readonly GOPATH="${GOPATH%%:*}"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
check_fmt
|
||||||
|
check_lint
|
||||||
|
}
|
||||||
|
|
||||||
|
check_fmt() {
|
||||||
|
eval "set -e"
|
||||||
|
for file in $(git ls-files '*.go') ; do
|
||||||
|
gofmt $file | diff -u $file -
|
||||||
|
done
|
||||||
|
eval "set +e"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_lint() {
|
||||||
|
_install_linter
|
||||||
|
|
||||||
|
for file in $(git ls-files '*.go') ; do
|
||||||
|
if [[ ! "$(${GOPATH}/bin/golint $file)" =~ ^[[:blank:]]*$ ]] ; then
|
||||||
|
_lint_verbose && exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
_lint_verbose() {
|
||||||
|
for file in $(git ls-files '*.go') ; do $GOPATH/bin/golint $file ; done
|
||||||
|
}
|
||||||
|
|
||||||
|
_install_linter() {
|
||||||
|
if [[ ! -x "${GOPATH}/bin/golint" ]] ; then
|
||||||
|
go get -u github.com/golang/lint/golint
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main "$@"
|
3
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/.dockerignore
generated
vendored
Normal file
3
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/.dockerignore
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
container.tar
|
||||||
|
dockerfile.tar
|
||||||
|
foofile
|
0
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/barfile
generated
vendored
Normal file
0
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/barfile
generated
vendored
Normal file
18
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/ca.pem
generated
vendored
Normal file
18
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/ca.pem
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC1TCCAb+gAwIBAgIQJ9MsNxrUxumNbAytGi3GEDALBgkqhkiG9w0BAQswFjEU
|
||||||
|
MBIGA1UEChMLQm9vdDJEb2NrZXIwHhcNMTQxMDE2MjAyMTM4WhcNMTcwOTMwMjAy
|
||||||
|
MTM4WjAWMRQwEgYDVQQKEwtCb290MkRvY2tlcjCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
ggEPADCCAQoCggEBALpFCSARjG+5yXoqr7UMzuE0df7RRZfeRZI06lJ02ZqV4Iii
|
||||||
|
rgL7ML9yPxX50NbLnjiilSDTUhnyocYFItokzUzz8qpX/nlYhuN2Iqwh4d0aWS8z
|
||||||
|
f5y248F+H1z+HY2W8NPl/6DVlVwYaNW1/k+RPMlHS0INLR6j+3Ievew7RNE0NnM2
|
||||||
|
znELW6NetekDt3GUcz0Z95vDUDfdPnIk1eIFMmYvLxZh23xOca4Q37a3S8F3d+dN
|
||||||
|
+OOpwjdgY9Qme0NQUaXpgp58jWuQfB8q7mZrdnLlLqRa8gx1HeDSotX7UmWtWPkb
|
||||||
|
vd9EdlKLYw5PVpxMV1rkwf2t4TdgD5NfkpXlXkkCAwEAAaMjMCEwDgYDVR0PAQH/
|
||||||
|
BAQDAgCkMA8GA1UdEwEB/wQFMAMBAf8wCwYJKoZIhvcNAQELA4IBAQBxYjHVSKqE
|
||||||
|
MJw7CW0GddesULtXXVWGJuZdWJLQlPvPMfIfjIvlcZyS4cdVNiQ3sREFIZz8TpII
|
||||||
|
CT0/Pg3sgv/FcOQe1CN0xZYZcyiAZHK1z0fJQq2qVpdv7+tJcjI2vvU6NI24iQCo
|
||||||
|
W1wz25trJz9QbdB2MRLMjyz7TSWuafztIvcfEzaIdQ0Whqund/cSuPGQx5IwF83F
|
||||||
|
rvlkOyJSH2+VIEBTCIuykJeL0DLTt8cePBQR5L1ISXb4RUMK9ZtqRscBRv8sn7o2
|
||||||
|
ixG3wtL0gYF4xLtsQWVxI3iFVrU3WzOH/3c5shVRkWBd+AQRSwCJI4mKH7penJCF
|
||||||
|
i3/zzlkvOnjV
|
||||||
|
-----END CERTIFICATE-----
|
18
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/cert.pem
generated
vendored
Normal file
18
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/cert.pem
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC6DCCAdKgAwIBAgIRANO6ymxQAjp66KmEka1G6b0wCwYJKoZIhvcNAQELMBYx
|
||||||
|
FDASBgNVBAoTC0Jvb3QyRG9ja2VyMB4XDTE0MTAxNjIwMjE1MloXDTE3MDkzMDIw
|
||||||
|
MjE1MlowFjEUMBIGA1UEChMLQm9vdDJEb2NrZXIwggEiMA0GCSqGSIb3DQEBAQUA
|
||||||
|
A4IBDwAwggEKAoIBAQDGA1mAhSOpZspD1dpZ7qVEQrIJw4Xo8252jHaORnEdDiFm
|
||||||
|
b6brEmr6jw8t4P3IGxbqBc/TqRV+SSXxwYEVvfpeQKH+SmqStoMNtD3Ura161az4
|
||||||
|
V0BcxMtSlsUGpoz+//QCAq8qiaxMwgiyc5253mkQm88anj2cNt7xbewiu/KFWuf7
|
||||||
|
BVpNK1+ltpJmlukfcj/G+I1bw7j1KxBjDrFqe5cyDuuZcDL2tmUXP/ZWDyXwSv+H
|
||||||
|
AOckqn44z6aXlBkVvOXDBZJqY76d/vWVDNCuZeXRnqlhP3t1kH4V0RQXo+JD2tgt
|
||||||
|
JgdU0unzyoFOSWNUBPm73tqmjUGGAmGHBmeegJr/AgMBAAGjNTAzMA4GA1UdDwEB
|
||||||
|
/wQEAwIAgDATBgNVHSUEDDAKBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMAsGCSqG
|
||||||
|
SIb3DQEBCwOCAQEABVTWl5SmBP+j5He5bQsgnIXjviSKqe40/10V4LJAOmilycRF
|
||||||
|
zLrzM+YMwfjg6PLIs8CldAMWHw9y9ktZY4MxkgCktaiaN/QmMTMwFWEcN4wy5IpM
|
||||||
|
U5l93eAg7xsnY430h3QBBADujX4wdF3fs8rSL8zAAQFL0ihurwU124K3yXKsrwpb
|
||||||
|
CiVUGfIN4sPwjy8Ws9oxHFDC9/P8lgjHZ1nBIf8KSHnMzlxDGj7isQfhtH+7mcCL
|
||||||
|
cM1qO2NirS2v7uaEPPY+MJstAz+W7EJCW9dfMSmHna2SDC37Xkin7uEY9z+qaKFL
|
||||||
|
8d/XxOB/L8Ucy8VZhdsv0dsBq5KfJntITM0ksQ==
|
||||||
|
-----END CERTIFICATE-----
|
0
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/foofile
generated
vendored
Normal file
0
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/foofile
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/key.pem
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/key.pem
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEowIBAAKCAQEAxgNZgIUjqWbKQ9XaWe6lREKyCcOF6PNudox2jkZxHQ4hZm+m
|
||||||
|
6xJq+o8PLeD9yBsW6gXP06kVfkkl8cGBFb36XkCh/kpqkraDDbQ91K2tetWs+FdA
|
||||||
|
XMTLUpbFBqaM/v/0AgKvKomsTMIIsnOdud5pEJvPGp49nDbe8W3sIrvyhVrn+wVa
|
||||||
|
TStfpbaSZpbpH3I/xviNW8O49SsQYw6xanuXMg7rmXAy9rZlFz/2Vg8l8Er/hwDn
|
||||||
|
JKp+OM+ml5QZFbzlwwWSamO+nf71lQzQrmXl0Z6pYT97dZB+FdEUF6PiQ9rYLSYH
|
||||||
|
VNLp88qBTkljVAT5u97apo1BhgJhhwZnnoCa/wIDAQABAoIBAQCaGy9EC9pmU95l
|
||||||
|
DwGh7k5nIrUnTilg1FwLHWSDdCVCZKXv8ENrPelOWZqJrUo1u4eI2L8XTsewgkNq
|
||||||
|
tJu/DRzWz9yDaO0qg6rZNobMh+K076lvmZA44twOydJLS8H+D7ua+PXU2FLlZjmY
|
||||||
|
kMyXRJZmW6zCXZc7haTbJx6ZJccoquk/DkS4FcFurJP177u1YrWS9TTw9kensUtU
|
||||||
|
jQ63uf56UTN1i+0+Rxl7OW1TZlqwlri5I4njg5249+FxwwHzIq8+l7zD7K9pl8c/
|
||||||
|
nG1HuulvU2bVlDlRdyslMPAH34vw9Sku1BD8furrJLr1na5lRSLKJODEaIPEsLwv
|
||||||
|
CdEUwP9JAoGBAO76ZW80RyNB2fA+wbTq70Sr8CwrXxYemXrez5LKDC7SsohKFCPE
|
||||||
|
IedpO/n+nmymiiJvMm874EExoG6BVrbkWkeb+2vinEfOQNlDMsDx7WLjPekP3t6i
|
||||||
|
rXHO3CjFooVFq2z3mZa/Nc5NZqu8fNWNCKJxZDJphdoj6sORNJIUvZVjAoGBANQd
|
||||||
|
++J+ITcu3/+A6JrGcgLunBFQYPqkiItk0J4QKYKuX5ik9rWcQDN8TTtfW2mDuiQ4
|
||||||
|
NrCwuVPq1V1kB16JzH017SsYLo9g8I20YjnBZge9pKTeUaLVTb3C50LW8FBylop0
|
||||||
|
Bnm597dNbtSjphjoTMg0XyC19o3Esf2YeWG0QNS1AoGAWWDfFRNJU99qIldmXULM
|
||||||
|
0DM6NVrXSk+ReYnhunXEzrJQwXZrR+EwCPurydk36Uz0NuK9yypquhdUeF/5TZfk
|
||||||
|
SAoHo5byekyipl9imRUigqyY2BTudvgCxKDoaHtaSFwBPFTyZZYICquaLbrmOXxw
|
||||||
|
8UhVgCFFRYvPXuts7QHC0h8CgYBWEvy9gfU0kV7wLX02IUTuj6jhFb7ktpN6DSTi
|
||||||
|
nyhZES1VoctDEu6ydcRZTW6ouH12aSE4Pd5WgTqntQmQgVZrkNB25k8ue2Xh+srJ
|
||||||
|
KQOgLIJ9LIHwE6KCWG7DnrjRzE3uTPq7to0g4tkQjH/AJ7PQof/gJDayfJjFkXPg
|
||||||
|
A+cy6QKBgEPbKpiqscm03gT2QanBut5pg4dqPOxp0SlErA3kSFNTRK3oYBQPC+LH
|
||||||
|
qA5nD5brdkeNBB58Rll8Zpzxiff50bcvLP/7/Sb3NjaXFTEY0gVbdRof3n6N0YP3
|
||||||
|
Hu5XDNJ9RNkNzE5RIG1g86KE+aKlcrKMaigqAiuIy2PSnjkQeGk8
|
||||||
|
-----END RSA PRIVATE KEY-----
|
18
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/server.pem
generated
vendored
Normal file
18
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/server.pem
generated
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIC/DCCAeagAwIBAgIQMUILcXtvmSOK63zEBo0VXzALBgkqhkiG9w0BAQswFjEU
|
||||||
|
MBIGA1UEChMLQm9vdDJEb2NrZXIwHhcNMTQxMDE2MjAyMTQ2WhcNMTcwOTMwMjAy
|
||||||
|
MTQ2WjAWMRQwEgYDVQQKEwtCb290MkRvY2tlcjCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||||
|
ggEPADCCAQoCggEBANxUOUhNnqFnrTlLsBYzfFRZWQo268l+4K4lOJCVbfDonP3g
|
||||||
|
Mz0vGi9fcyFqEWSA8Y+ShXna625HTnReCwFdsu0861qCIq7v95hFFCyOe0iIxpd0
|
||||||
|
AKLnl90d+1vonE7andgFgoobbTiMly4UK4H6z8D148fFNIihoteOG3PIF89TFxP7
|
||||||
|
CJ/3wXnx/IKpdlO8PAnub3tBPJHvGDj7KORLy4IBxRX5VBAdfGNybE66fcrehEva
|
||||||
|
rLA4m9pgiaR/Nnr9FdKhPyqYdjflLNvzydxNvMIV4M0hFlhXmYvpMjA5/XsTnsyV
|
||||||
|
t9JHJa5Upwqsbne08t7rsm7liZNxZlko8xPOTQcCAwEAAaNKMEgwDgYDVR0PAQH/
|
||||||
|
BAQDAgCgMAwGA1UdEwEB/wQCMAAwKAYDVR0RBCEwH4ILYm9vdDJkb2NrZXKHBH8A
|
||||||
|
AAGHBAoAAg+HBMCoO2cwCwYJKoZIhvcNAQELA4IBAQAYoYcDkDWkl73FZ0WnPmAj
|
||||||
|
LiF7HU95Qg3KyEpFsAJeShSLPPbQntmwhdekEzY4tQ3eKQB/+zHFjzsCr/lmDUmH
|
||||||
|
Ea/ryQ17C+jyH+Ykg0IWW6L6veZhvRDg6Z9focVtPVBRxPTqC/Qhb54blWRASV+W
|
||||||
|
UreMuXQ5+1dQptAM7ixOeLVHjBi/bd9TL3jvwBVCr9QedteMjjK4TCF9Tbcou+MF
|
||||||
|
2w3OJJZMDhcD+YwoK9uJDqlKmcTm/vVMbSsp/pTMcnQ7jxCeR8/XyX+VwTZwaHAa
|
||||||
|
o92Q/eg3THAiWhvyT/SzyH9dHHBAyXynUwGCggKawHktfvW4QXRPuLxLrJ7iB5cy
|
||||||
|
-----END CERTIFICATE-----
|
27
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/serverkey.pem
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/serverkey.pem
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEoAIBAAKCAQEA3FQ5SE2eoWetOUuwFjN8VFlZCjbryX7griU4kJVt8Oic/eAz
|
||||||
|
PS8aL19zIWoRZIDxj5KFedrrbkdOdF4LAV2y7TzrWoIiru/3mEUULI57SIjGl3QA
|
||||||
|
oueX3R37W+icTtqd2AWCihttOIyXLhQrgfrPwPXjx8U0iKGi144bc8gXz1MXE/sI
|
||||||
|
n/fBefH8gql2U7w8Ce5ve0E8ke8YOPso5EvLggHFFflUEB18Y3JsTrp9yt6ES9qs
|
||||||
|
sDib2mCJpH82ev0V0qE/Kph2N+Us2/PJ3E28whXgzSEWWFeZi+kyMDn9exOezJW3
|
||||||
|
0kclrlSnCqxud7Ty3uuybuWJk3FmWSjzE85NBwIDAQABAoIBAG0ak+cW8LeShHf7
|
||||||
|
3+2Of0GxoOLrAWWdG5uAuPr31CJYve0FybnBimDtDjD8ujIfm/7xmoEWBEFutA3x
|
||||||
|
x9dcU88gvJbsHEqub9gKVQwfXjMz78tt2SbSMiR/xUnk7QorPcCMMfE71aEMFYzu
|
||||||
|
1gCed6Rg3vO81t/V0rKVH0j9S7UQz5v/oX15eVDV5LOqyCHwAi6K0eXXbqnbI0TH
|
||||||
|
SOQ/nexM2msVXWbO9t6ra6f5V7FXziDK5Xi+rPxRbX9mkrDzxDAevfuRqYBx5vtL
|
||||||
|
W2Q2hKjUAHFgXFniNSZBS7dCdAtz0el/3ct+cNmpuTMhhs7M6wC1CuYiZ/DxLiFh
|
||||||
|
Si73VckCgYEA+/ceh3+VjtQ0rgEw8sD9bqYEA8IaBiObjneIoFnKBYRG7yZd8JMm
|
||||||
|
HD4M/aQ1qhcRLPN7GR03YQULgQJURbKSjJHnhfTXHyeHC3NN4gMVHQXewu2MHCh6
|
||||||
|
7FCQ9CfK0KcYLgegVVvL3PrF3hyWGnmTu+G0UkDQRYVnaNrB7snrW6UCgYEA39tq
|
||||||
|
+MCQdu0moJ5szSZf02undg9EeW6isk9qzi7TId3/MLci2eH7PEnipipPUK3+DERq
|
||||||
|
aba0y0TKgBR2EXvXLFJA/+kfdo2loIEHOfox85HVfxgUaFRti63ZI0uF8D0QT2Yy
|
||||||
|
oJal+RFghVoSnv4LjhRKEPbIkScTXGjdK+7wFjsCfz79iKRXQQx0ALd/lL0bgkAn
|
||||||
|
QNmvrNHcFQeI2p8700WNzC39aX67SsvEt3qxkrjzC1gxhpTAuReIK1gVPPwvqHN8
|
||||||
|
BmV20FD5kMlMCix2mNCopwgUWvKvLAvoGFTxncKMA39+aJbuXAjiqJTekKgNvOE7
|
||||||
|
i9kEWw0GTNPp3JHV6QECgYAPwb0M11kT1euDIMOdyRazpf86kyaJuZzgGjD1ZFxe
|
||||||
|
JOcigbGFTp/FhZnbglzk2+pm6KXo3QBq0mPCki4hWusxZnTGzpz1VlETNCHTFeZQ
|
||||||
|
M7KoaIR/N3oie9Et59H8r/+m5xWnMhNqratyl316DX24uXrhKM3DUdHODl+LCR2D
|
||||||
|
IwKBgE1MbHuwolUPEw3HeO4R7NMFVTFei7E/fpUsimPfArGg8UydwvloNT1myJos
|
||||||
|
N2JzfGGjN2KPVcBk9fOs71mJ6VcK3C3g5JIccplk6h9VNaw55+zdQvKPTzoBoTvy
|
||||||
|
A+Fwx2AlF61KeRF87DL2YTRJ6B9MHmWgf7+GVZOxomLgEAcZ
|
||||||
|
-----END RSA PRIVATE KEY-----
|
1
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/symlink
generated
vendored
Symbolic link
1
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/data/symlink
generated
vendored
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
doesnotexist
|
70
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/server.go
generated
vendored
70
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/server.go
generated
vendored
@ -34,6 +34,7 @@ import (
|
|||||||
// For more details on the remote API, check http://goo.gl/G3plxW.
|
// For more details on the remote API, check http://goo.gl/G3plxW.
|
||||||
type DockerServer struct {
|
type DockerServer struct {
|
||||||
containers []*docker.Container
|
containers []*docker.Container
|
||||||
|
execs []*docker.Exec
|
||||||
cMut sync.RWMutex
|
cMut sync.RWMutex
|
||||||
images []docker.Image
|
images []docker.Image
|
||||||
iMut sync.RWMutex
|
iMut sync.RWMutex
|
||||||
@ -90,18 +91,22 @@ func (s *DockerServer) buildMuxer() {
|
|||||||
s.mux.Path("/containers/{id:.*}/json").Methods("GET").HandlerFunc(s.handlerWrapper(s.inspectContainer))
|
s.mux.Path("/containers/{id:.*}/json").Methods("GET").HandlerFunc(s.handlerWrapper(s.inspectContainer))
|
||||||
s.mux.Path("/containers/{id:.*}/top").Methods("GET").HandlerFunc(s.handlerWrapper(s.topContainer))
|
s.mux.Path("/containers/{id:.*}/top").Methods("GET").HandlerFunc(s.handlerWrapper(s.topContainer))
|
||||||
s.mux.Path("/containers/{id:.*}/start").Methods("POST").HandlerFunc(s.handlerWrapper(s.startContainer))
|
s.mux.Path("/containers/{id:.*}/start").Methods("POST").HandlerFunc(s.handlerWrapper(s.startContainer))
|
||||||
|
s.mux.Path("/containers/{id:.*}/kill").Methods("POST").HandlerFunc(s.handlerWrapper(s.stopContainer))
|
||||||
s.mux.Path("/containers/{id:.*}/stop").Methods("POST").HandlerFunc(s.handlerWrapper(s.stopContainer))
|
s.mux.Path("/containers/{id:.*}/stop").Methods("POST").HandlerFunc(s.handlerWrapper(s.stopContainer))
|
||||||
s.mux.Path("/containers/{id:.*}/pause").Methods("POST").HandlerFunc(s.handlerWrapper(s.pauseContainer))
|
s.mux.Path("/containers/{id:.*}/pause").Methods("POST").HandlerFunc(s.handlerWrapper(s.pauseContainer))
|
||||||
s.mux.Path("/containers/{id:.*}/unpause").Methods("POST").HandlerFunc(s.handlerWrapper(s.unpauseContainer))
|
s.mux.Path("/containers/{id:.*}/unpause").Methods("POST").HandlerFunc(s.handlerWrapper(s.unpauseContainer))
|
||||||
s.mux.Path("/containers/{id:.*}/wait").Methods("POST").HandlerFunc(s.handlerWrapper(s.waitContainer))
|
s.mux.Path("/containers/{id:.*}/wait").Methods("POST").HandlerFunc(s.handlerWrapper(s.waitContainer))
|
||||||
s.mux.Path("/containers/{id:.*}/attach").Methods("POST").HandlerFunc(s.handlerWrapper(s.attachContainer))
|
s.mux.Path("/containers/{id:.*}/attach").Methods("POST").HandlerFunc(s.handlerWrapper(s.attachContainer))
|
||||||
s.mux.Path("/containers/{id:.*}").Methods("DELETE").HandlerFunc(s.handlerWrapper(s.removeContainer))
|
s.mux.Path("/containers/{id:.*}").Methods("DELETE").HandlerFunc(s.handlerWrapper(s.removeContainer))
|
||||||
|
s.mux.Path("/containers/{id:.*}/exec").Methods("POST").HandlerFunc(s.handlerWrapper(s.createExecContainer))
|
||||||
|
s.mux.Path("/exec/{id:.*}/start").Methods("POST").HandlerFunc(s.handlerWrapper(s.startExecContainer))
|
||||||
s.mux.Path("/images/create").Methods("POST").HandlerFunc(s.handlerWrapper(s.pullImage))
|
s.mux.Path("/images/create").Methods("POST").HandlerFunc(s.handlerWrapper(s.pullImage))
|
||||||
s.mux.Path("/build").Methods("POST").HandlerFunc(s.handlerWrapper(s.buildImage))
|
s.mux.Path("/build").Methods("POST").HandlerFunc(s.handlerWrapper(s.buildImage))
|
||||||
s.mux.Path("/images/json").Methods("GET").HandlerFunc(s.handlerWrapper(s.listImages))
|
s.mux.Path("/images/json").Methods("GET").HandlerFunc(s.handlerWrapper(s.listImages))
|
||||||
s.mux.Path("/images/{id:.*}").Methods("DELETE").HandlerFunc(s.handlerWrapper(s.removeImage))
|
s.mux.Path("/images/{id:.*}").Methods("DELETE").HandlerFunc(s.handlerWrapper(s.removeImage))
|
||||||
s.mux.Path("/images/{name:.*}/json").Methods("GET").HandlerFunc(s.handlerWrapper(s.inspectImage))
|
s.mux.Path("/images/{name:.*}/json").Methods("GET").HandlerFunc(s.handlerWrapper(s.inspectImage))
|
||||||
s.mux.Path("/images/{name:.*}/push").Methods("POST").HandlerFunc(s.handlerWrapper(s.pushImage))
|
s.mux.Path("/images/{name:.*}/push").Methods("POST").HandlerFunc(s.handlerWrapper(s.pushImage))
|
||||||
|
s.mux.Path("/images/{name:.*}/tag").Methods("POST").HandlerFunc(s.handlerWrapper(s.tagImage))
|
||||||
s.mux.Path("/events").Methods("GET").HandlerFunc(s.listEvents)
|
s.mux.Path("/events").Methods("GET").HandlerFunc(s.listEvents)
|
||||||
s.mux.Path("/_ping").Methods("GET").HandlerFunc(s.handlerWrapper(s.pingDocker))
|
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/load").Methods("POST").HandlerFunc(s.handlerWrapper(s.loadImage))
|
||||||
@ -173,8 +178,8 @@ func (s *DockerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns default http.Handler mux, it allows customHandlers to call the
|
// DefaultHandler returns default http.Handler mux, it allows customHandlers to
|
||||||
// default behavior if wanted.
|
// call the default behavior if wanted.
|
||||||
func (s *DockerServer) DefaultHandler() http.Handler {
|
func (s *DockerServer) DefaultHandler() http.Handler {
|
||||||
return s.mux
|
return s.mux
|
||||||
}
|
}
|
||||||
@ -210,6 +215,7 @@ func (s *DockerServer) listContainers(w http.ResponseWriter, r *http.Request) {
|
|||||||
Created: container.Created.Unix(),
|
Created: container.Created.Unix(),
|
||||||
Status: container.State.String(),
|
Status: container.State.String(),
|
||||||
Ports: container.NetworkSettings.PortMappingAPI(),
|
Ports: container.NetworkSettings.PortMappingAPI(),
|
||||||
|
Names: []string{fmt.Sprintf("/%s", container.Name)},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -269,8 +275,7 @@ func (s *DockerServer) createContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
image, err := s.findImage(config.Image)
|
if _, err := s.findImage(config.Image); err != nil {
|
||||||
if err != nil {
|
|
||||||
http.Error(w, err.Error(), http.StatusNotFound)
|
http.Error(w, err.Error(), http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -278,7 +283,7 @@ func (s *DockerServer) createContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
ports := map[docker.Port][]docker.PortBinding{}
|
ports := map[docker.Port][]docker.PortBinding{}
|
||||||
for port := range config.ExposedPorts {
|
for port := range config.ExposedPorts {
|
||||||
ports[port] = []docker.PortBinding{{
|
ports[port] = []docker.PortBinding{{
|
||||||
HostIp: "0.0.0.0",
|
HostIP: "0.0.0.0",
|
||||||
HostPort: strconv.Itoa(mathrand.Int() % 65536),
|
HostPort: strconv.Itoa(mathrand.Int() % 65536),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
@ -294,6 +299,7 @@ func (s *DockerServer) createContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
container := docker.Container{
|
container := docker.Container{
|
||||||
|
Name: r.URL.Query().Get("name"),
|
||||||
ID: s.generateID(),
|
ID: s.generateID(),
|
||||||
Created: time.Now(),
|
Created: time.Now(),
|
||||||
Path: path,
|
Path: path,
|
||||||
@ -305,7 +311,7 @@ func (s *DockerServer) createContainer(w http.ResponseWriter, r *http.Request) {
|
|||||||
ExitCode: 0,
|
ExitCode: 0,
|
||||||
StartedAt: time.Now(),
|
StartedAt: time.Now(),
|
||||||
},
|
},
|
||||||
Image: image,
|
Image: config.Image,
|
||||||
NetworkSettings: &docker.NetworkSettings{
|
NetworkSettings: &docker.NetworkSettings{
|
||||||
IPAddress: fmt.Sprintf("172.16.42.%d", mathrand.Int()%250+2),
|
IPAddress: fmt.Sprintf("172.16.42.%d", mathrand.Int()%250+2),
|
||||||
IPPrefixLen: 24,
|
IPPrefixLen: 24,
|
||||||
@ -557,8 +563,10 @@ func (s *DockerServer) buildImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
//we did not use that Dockerfile to build image cause we are a fake Docker daemon
|
//we did not use that Dockerfile to build image cause we are a fake Docker daemon
|
||||||
image := docker.Image{
|
image := docker.Image{
|
||||||
ID: s.generateID(),
|
ID: s.generateID(),
|
||||||
|
Created: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
query := r.URL.Query()
|
query := r.URL.Query()
|
||||||
repository := image.ID
|
repository := image.ID
|
||||||
if t := query.Get("t"); t != "" {
|
if t := query.Get("t"); t != "" {
|
||||||
@ -597,6 +605,22 @@ func (s *DockerServer) pushImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Fprintln(w, "Pushed")
|
fmt.Fprintln(w, "Pushed")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerServer) tagImage(w http.ResponseWriter, r *http.Request) {
|
||||||
|
name := mux.Vars(r)["name"]
|
||||||
|
s.iMut.RLock()
|
||||||
|
if _, ok := s.imgIDs[name]; !ok {
|
||||||
|
s.iMut.RUnlock()
|
||||||
|
http.Error(w, "No such image", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.iMut.RUnlock()
|
||||||
|
s.iMut.Lock()
|
||||||
|
defer s.iMut.Unlock()
|
||||||
|
newRepo := r.URL.Query().Get("repo")
|
||||||
|
s.imgIDs[newRepo] = s.imgIDs[name]
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *DockerServer) removeImage(w http.ResponseWriter, r *http.Request) {
|
func (s *DockerServer) removeImage(w http.ResponseWriter, r *http.Request) {
|
||||||
id := mux.Vars(r)["id"]
|
id := mux.Vars(r)["id"]
|
||||||
s.iMut.RLock()
|
s.iMut.RLock()
|
||||||
@ -604,6 +628,12 @@ func (s *DockerServer) removeImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
if img, ok := s.imgIDs[id]; ok {
|
if img, ok := s.imgIDs[id]; ok {
|
||||||
id, tag = img, id
|
id, tag = img, id
|
||||||
}
|
}
|
||||||
|
var tags []string
|
||||||
|
for tag, taggedID := range s.imgIDs {
|
||||||
|
if taggedID == id {
|
||||||
|
tags = append(tags, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
s.iMut.RUnlock()
|
s.iMut.RUnlock()
|
||||||
_, index, err := s.findImageByID(id)
|
_, index, err := s.findImageByID(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -613,8 +643,10 @@ func (s *DockerServer) removeImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.WriteHeader(http.StatusNoContent)
|
w.WriteHeader(http.StatusNoContent)
|
||||||
s.iMut.Lock()
|
s.iMut.Lock()
|
||||||
defer s.iMut.Unlock()
|
defer s.iMut.Unlock()
|
||||||
s.images[index] = s.images[len(s.images)-1]
|
if len(tags) < 2 {
|
||||||
s.images = s.images[:len(s.images)-1]
|
s.images[index] = s.images[len(s.images)-1]
|
||||||
|
s.images = s.images[:len(s.images)-1]
|
||||||
|
}
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
delete(s.imgIDs, tag)
|
delete(s.imgIDs, tag)
|
||||||
}
|
}
|
||||||
@ -690,3 +722,23 @@ func (s *DockerServer) getImage(w http.ResponseWriter, r *http.Request) {
|
|||||||
w.Header().Set("Content-Type", "application/tar")
|
w.Header().Set("Content-Type", "application/tar")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *DockerServer) createExecContainer(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
exec := docker.Exec{ID: "id-exec-created-by-test"}
|
||||||
|
s.execs = append(s.execs, &exec)
|
||||||
|
json.NewEncoder(w).Encode(map[string]string{"Id": exec.ID})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *DockerServer) startExecContainer(w http.ResponseWriter, r *http.Request) {
|
||||||
|
id := mux.Vars(r)["id"]
|
||||||
|
for _, exec := range s.execs {
|
||||||
|
if exec.ID == id {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
}
|
||||||
|
74
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/server_test.go
generated
vendored
74
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/server_test.go
generated
vendored
@ -120,6 +120,7 @@ func TestListContainers(t *testing.T) {
|
|||||||
Created: container.Created.Unix(),
|
Created: container.Created.Unix(),
|
||||||
Status: container.State.String(),
|
Status: container.State.String(),
|
||||||
Ports: container.NetworkSettings.PortMappingAPI(),
|
Ports: container.NetworkSettings.PortMappingAPI(),
|
||||||
|
Names: []string{"/" + container.Name},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var got []docker.APIContainers
|
var got []docker.APIContainers
|
||||||
@ -473,6 +474,23 @@ func TestStopContainer(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestKillContainer(t *testing.T) {
|
||||||
|
server := DockerServer{}
|
||||||
|
addContainers(&server, 1)
|
||||||
|
server.containers[0].State.Running = true
|
||||||
|
server.buildMuxer()
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
path := fmt.Sprintf("/containers/%s/kill", server.containers[0].ID)
|
||||||
|
request, _ := http.NewRequest("POST", path, nil)
|
||||||
|
server.ServeHTTP(recorder, request)
|
||||||
|
if recorder.Code != http.StatusNoContent {
|
||||||
|
t.Errorf("KillContainer: wrong status code. Want %d. Got %d.", http.StatusNoContent, recorder.Code)
|
||||||
|
}
|
||||||
|
if server.containers[0].State.Running {
|
||||||
|
t.Error("KillContainer: did not stop the container")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestStopContainerWithNotifyChannel(t *testing.T) {
|
func TestStopContainerWithNotifyChannel(t *testing.T) {
|
||||||
ch := make(chan *docker.Container, 1)
|
ch := make(chan *docker.Container, 1)
|
||||||
server := DockerServer{}
|
server := DockerServer{}
|
||||||
@ -771,12 +789,38 @@ func TestPushImageNotFound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestTagImage(t *testing.T) {
|
||||||
|
server := DockerServer{imgIDs: map[string]string{"tsuru/python": "a123"}}
|
||||||
|
server.buildMuxer()
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
request, _ := http.NewRequest("POST", "/images/tsuru/python/tag?repo=tsuru/new-python", nil)
|
||||||
|
server.ServeHTTP(recorder, request)
|
||||||
|
if recorder.Code != http.StatusCreated {
|
||||||
|
t.Errorf("TagImage: wrong status. Want %d. Got %d.", http.StatusCreated, recorder.Code)
|
||||||
|
}
|
||||||
|
if server.imgIDs["tsuru/python"] != server.imgIDs["tsuru/new-python"] {
|
||||||
|
t.Errorf("TagImage: did not tag the image")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestTagImageNotFound(t *testing.T) {
|
||||||
|
server := DockerServer{}
|
||||||
|
server.buildMuxer()
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
request, _ := http.NewRequest("POST", "/images/tsuru/python/tag", nil)
|
||||||
|
server.ServeHTTP(recorder, request)
|
||||||
|
if recorder.Code != http.StatusNotFound {
|
||||||
|
t.Errorf("TagImage: wrong status. Want %d. Got %d.", http.StatusNotFound, recorder.Code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func addContainers(server *DockerServer, n int) {
|
func addContainers(server *DockerServer, n int) {
|
||||||
server.cMut.Lock()
|
server.cMut.Lock()
|
||||||
defer server.cMut.Unlock()
|
defer server.cMut.Unlock()
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
date := time.Now().Add(time.Duration((rand.Int() % (i + 1))) * time.Hour)
|
date := time.Now().Add(time.Duration((rand.Int() % (i + 1))) * time.Hour)
|
||||||
container := docker.Container{
|
container := docker.Container{
|
||||||
|
Name: fmt.Sprintf("%x", rand.Int()%10000),
|
||||||
ID: fmt.Sprintf("%x", rand.Int()%10000),
|
ID: fmt.Sprintf("%x", rand.Int()%10000),
|
||||||
Created: date,
|
Created: date,
|
||||||
Path: "ls",
|
Path: "ls",
|
||||||
@ -896,6 +940,36 @@ func TestRemoveImageByName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRemoveImageWithMultipleTags(t *testing.T) {
|
||||||
|
server := DockerServer{}
|
||||||
|
addImages(&server, 1, true)
|
||||||
|
server.buildMuxer()
|
||||||
|
imgID := server.images[0].ID
|
||||||
|
imgName := "docker/python-" + imgID
|
||||||
|
server.imgIDs["docker/python-wat"] = imgID
|
||||||
|
recorder := httptest.NewRecorder()
|
||||||
|
path := fmt.Sprintf("/images/%s", imgName)
|
||||||
|
request, _ := http.NewRequest("DELETE", path, nil)
|
||||||
|
server.ServeHTTP(recorder, request)
|
||||||
|
_, ok := server.imgIDs[imgName]
|
||||||
|
if ok {
|
||||||
|
t.Error("RemoveImage: did not remove image tag name.")
|
||||||
|
}
|
||||||
|
id, ok := server.imgIDs["docker/python-wat"]
|
||||||
|
if !ok {
|
||||||
|
t.Error("RemoveImage: removed the wrong tag name.")
|
||||||
|
}
|
||||||
|
if id != imgID {
|
||||||
|
t.Error("RemoveImage: disassociated the wrong ID from the tag")
|
||||||
|
}
|
||||||
|
if len(server.images) < 1 {
|
||||||
|
t.Fatal("RemoveImage: removed the image, but should keep it")
|
||||||
|
}
|
||||||
|
if server.images[0].ID != imgID {
|
||||||
|
t.Error("RemoveImage: changed the ID of the image!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestPrepareFailure(t *testing.T) {
|
func TestPrepareFailure(t *testing.T) {
|
||||||
server := DockerServer{failures: make(map[string]string)}
|
server := DockerServer{failures: make(map[string]string)}
|
||||||
server.buildMuxer()
|
server.buildMuxer()
|
||||||
|
6
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/writer.go
generated
vendored
6
Godeps/_workspace/src/github.com/fsouza/go-dockerclient/testing/writer.go
generated
vendored
@ -13,9 +13,9 @@ import (
|
|||||||
type stdType [8]byte
|
type stdType [8]byte
|
||||||
|
|
||||||
var (
|
var (
|
||||||
stdin stdType = stdType{0: 0}
|
stdin = stdType{0: 0}
|
||||||
stdout stdType = stdType{0: 1}
|
stdout = stdType{0: 1}
|
||||||
stderr stdType = stdType{0: 2}
|
stderr = stdType{0: 2}
|
||||||
)
|
)
|
||||||
|
|
||||||
type stdWriter struct {
|
type stdWriter struct {
|
||||||
|
Loading…
Reference in New Issue
Block a user