mirror of https://github.com/docker/docs.git
add support some run options
Signed-off-by: Xian Chaobo <xianchaobo@huawei.com>
This commit is contained in:
parent
975eaa9e73
commit
c947d5be69
|
@ -1,15 +0,0 @@
|
|||
package dockerclient
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAuthEncode(t *testing.T) {
|
||||
a := AuthConfig{Username: "foo", Password: "password", Email: "bar@baz.com"}
|
||||
expected := "eyJ1c2VybmFtZSI6ImZvbyIsInBhc3N3b3JkIjoicGFzc3dvcmQiLCJlbWFpbCI6ImJhckBiYXouY29tIn0K"
|
||||
got, _ := a.encode()
|
||||
|
||||
if expected != got {
|
||||
t.Errorf("testAuthEncode failed. Expected [%s] got [%s]", expected, got)
|
||||
}
|
||||
}
|
|
@ -1,241 +0,0 @@
|
|||
package dockerclient
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
)
|
||||
|
||||
func assertEqual(t *testing.T, a interface{}, b interface{}, message string) {
|
||||
if a == b {
|
||||
return
|
||||
}
|
||||
if len(message) == 0 {
|
||||
message = fmt.Sprintf("%v != %v", a, b)
|
||||
}
|
||||
t.Fatal(message)
|
||||
}
|
||||
|
||||
func testDockerClient(t *testing.T) *DockerClient {
|
||||
client, err := NewDockerClient(testHTTPServer.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatal("Cannot init the docker client")
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
info, err := client.Info()
|
||||
if err != nil {
|
||||
t.Fatal("Cannot get server info")
|
||||
}
|
||||
assertEqual(t, info.Images, int64(1), "")
|
||||
assertEqual(t, info.Containers, int64(2), "")
|
||||
}
|
||||
|
||||
func TestKillContainer(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
if err := client.KillContainer("23132acf2ac", "5"); err != nil {
|
||||
t.Fatal("cannot kill container: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWait(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
|
||||
// This provokes an error on the server.
|
||||
select {
|
||||
case wr := <-client.Wait("1234"):
|
||||
assertEqual(t, wr.ExitCode, int(-1), "")
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("Timed out!")
|
||||
}
|
||||
|
||||
// Valid case.
|
||||
select {
|
||||
case wr := <-client.Wait("valid-id"):
|
||||
assertEqual(t, wr.ExitCode, int(0), "")
|
||||
case <-time.After(2 * time.Second):
|
||||
t.Fatal("Timed out!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPullImage(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
err := client.PullImage("busybox", nil)
|
||||
if err != nil {
|
||||
t.Fatal("unable to pull busybox")
|
||||
}
|
||||
|
||||
err = client.PullImage("haproxy", nil)
|
||||
if err != nil {
|
||||
t.Fatal("unable to pull haproxy")
|
||||
}
|
||||
|
||||
err = client.PullImage("wrongimg", nil)
|
||||
if err == nil {
|
||||
t.Fatal("should return error when it fails to pull wrongimg")
|
||||
}
|
||||
}
|
||||
|
||||
func TestListContainers(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
containers, err := client.ListContainers(true, false, "")
|
||||
if err != nil {
|
||||
t.Fatal("cannot get containers: %s", err)
|
||||
}
|
||||
assertEqual(t, len(containers), 1, "")
|
||||
cnt := containers[0]
|
||||
assertEqual(t, cnt.SizeRw, int64(0), "")
|
||||
}
|
||||
|
||||
func TestContainerChanges(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
changes, err := client.ContainerChanges("foobar")
|
||||
if err != nil {
|
||||
t.Fatal("cannot get container changes: %s", err)
|
||||
}
|
||||
assertEqual(t, len(changes), 3, "unexpected number of changes")
|
||||
c := changes[0]
|
||||
assertEqual(t, c.Path, "/dev", "unexpected")
|
||||
assertEqual(t, c.Kind, 0, "unexpected")
|
||||
}
|
||||
|
||||
func TestListContainersWithSize(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
containers, err := client.ListContainers(true, true, "")
|
||||
if err != nil {
|
||||
t.Fatal("cannot get containers: %s", err)
|
||||
}
|
||||
assertEqual(t, len(containers), 1, "")
|
||||
cnt := containers[0]
|
||||
assertEqual(t, cnt.SizeRw, int64(123), "")
|
||||
}
|
||||
|
||||
func TestListContainersWithFilters(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
containers, err := client.ListContainers(true, true, "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce']}")
|
||||
if err != nil {
|
||||
t.Fatal("cannot get containers: %s", err)
|
||||
}
|
||||
assertEqual(t, len(containers), 1, "")
|
||||
|
||||
containers, err = client.ListContainers(true, true, "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688cf']}")
|
||||
if err != nil {
|
||||
t.Fatal("cannot get containers: %s", err)
|
||||
}
|
||||
assertEqual(t, len(containers), 0, "")
|
||||
}
|
||||
|
||||
func TestContainerLogs(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
containerId := "foobar"
|
||||
logOptions := &LogOptions{
|
||||
Follow: true,
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
Timestamps: true,
|
||||
Tail: 10,
|
||||
}
|
||||
logsReader, err := client.ContainerLogs(containerId, logOptions)
|
||||
if err != nil {
|
||||
t.Fatal("cannot read logs from server")
|
||||
}
|
||||
|
||||
stdoutBuffer := new(bytes.Buffer)
|
||||
stderrBuffer := new(bytes.Buffer)
|
||||
if _, err = stdcopy.StdCopy(stdoutBuffer, stderrBuffer, logsReader); err != nil {
|
||||
t.Fatal("cannot read logs from logs reader")
|
||||
}
|
||||
stdoutLogs := strings.TrimSpace(stdoutBuffer.String())
|
||||
stderrLogs := strings.TrimSpace(stderrBuffer.String())
|
||||
stdoutLogLines := strings.Split(stdoutLogs, "\n")
|
||||
stderrLogLines := strings.Split(stderrLogs, "\n")
|
||||
if len(stdoutLogLines) != 5 {
|
||||
t.Fatalf("wrong number of stdout logs: len=%d", len(stdoutLogLines))
|
||||
}
|
||||
if len(stderrLogLines) != 5 {
|
||||
t.Fatalf("wrong number of stderr logs: len=%d", len(stdoutLogLines))
|
||||
}
|
||||
for i, line := range stdoutLogLines {
|
||||
expectedSuffix := fmt.Sprintf("Z line %d", 41+2*i)
|
||||
if !strings.HasSuffix(line, expectedSuffix) {
|
||||
t.Fatalf("expected stdout log line \"%s\" to end with \"%s\"", line, expectedSuffix)
|
||||
}
|
||||
}
|
||||
for i, line := range stderrLogLines {
|
||||
expectedSuffix := fmt.Sprintf("Z line %d", 40+2*i)
|
||||
if !strings.HasSuffix(line, expectedSuffix) {
|
||||
t.Fatalf("expected stderr log line \"%s\" to end with \"%s\"", line, expectedSuffix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonitorEvents(t *testing.T) {
|
||||
client := testDockerClient(t)
|
||||
decoder := json.NewDecoder(bytes.NewBufferString(eventsResp))
|
||||
var expectedEvents []Event
|
||||
for {
|
||||
var event Event
|
||||
if err := decoder.Decode(&event); err != nil {
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else {
|
||||
t.Fatalf("cannot parse expected resp: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
expectedEvents = append(expectedEvents, event)
|
||||
}
|
||||
}
|
||||
|
||||
// test passing stop chan
|
||||
stopChan := make(chan struct{})
|
||||
eventInfoChan, err := client.MonitorEvents(nil, stopChan)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot get events from server: %s", err.Error())
|
||||
}
|
||||
|
||||
eventInfo := <-eventInfoChan
|
||||
if eventInfo.Error != nil || eventInfo.Event != expectedEvents[0] {
|
||||
t.Fatalf("got:\n%#v\nexpected:\n%#v", eventInfo, expectedEvents[0])
|
||||
}
|
||||
close(stopChan)
|
||||
for i := 0; i < 3; i++ {
|
||||
_, ok := <-eventInfoChan
|
||||
if i == 2 && ok {
|
||||
t.Fatalf("read more than 2 events successfully after closing stopChan")
|
||||
}
|
||||
}
|
||||
|
||||
// test when you don't pass stop chan
|
||||
eventInfoChan, err = client.MonitorEvents(nil, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot get events from server: %s", err.Error())
|
||||
}
|
||||
|
||||
for i, expectedEvent := range expectedEvents {
|
||||
t.Logf("on iter %d\n", i)
|
||||
eventInfo := <-eventInfoChan
|
||||
if eventInfo.Error != nil || eventInfo.Event != expectedEvent {
|
||||
t.Fatalf("index %d, got:\n%#v\nexpected:\n%#v", i, eventInfo, expectedEvent)
|
||||
}
|
||||
t.Logf("done with iter %d\n", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDockerClientInterface(t *testing.T) {
|
||||
iface := reflect.TypeOf((*Client)(nil)).Elem()
|
||||
test := testDockerClient(t)
|
||||
|
||||
if !reflect.TypeOf(test).Implements(iface) {
|
||||
t.Fatalf("DockerClient does not implement the Client interface")
|
||||
}
|
||||
}
|
|
@ -1,245 +0,0 @@
|
|||
package dockerclient
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/jsonlog"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/docker/docker/pkg/timeutils"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
var (
|
||||
testHTTPServer *httptest.Server
|
||||
)
|
||||
|
||||
func init() {
|
||||
r := mux.NewRouter()
|
||||
baseURL := "/" + APIVersion
|
||||
r.HandleFunc(baseURL+"/info", handlerGetInfo).Methods("GET")
|
||||
r.HandleFunc(baseURL+"/containers/json", handlerGetContainers).Methods("GET")
|
||||
r.HandleFunc(baseURL+"/containers/{id}/logs", handleContainerLogs).Methods("GET")
|
||||
r.HandleFunc(baseURL+"/containers/{id}/changes", handleContainerChanges).Methods("GET")
|
||||
r.HandleFunc(baseURL+"/containers/{id}/kill", handleContainerKill).Methods("POST")
|
||||
r.HandleFunc(baseURL+"/containers/{id}/wait", handleWait).Methods("POST")
|
||||
r.HandleFunc(baseURL+"/images/create", handleImagePull).Methods("POST")
|
||||
r.HandleFunc(baseURL+"/events", handleEvents).Methods("GET")
|
||||
testHTTPServer = httptest.NewServer(handlerAccessLog(r))
|
||||
}
|
||||
|
||||
func handlerAccessLog(handler http.Handler) http.Handler {
|
||||
logHandler := func(w http.ResponseWriter, r *http.Request) {
|
||||
log.Printf("%s \"%s %s\"", r.RemoteAddr, r.Method, r.URL)
|
||||
handler.ServeHTTP(w, r)
|
||||
}
|
||||
return http.HandlerFunc(logHandler)
|
||||
}
|
||||
|
||||
func handleContainerKill(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "{%q:%q", "Id", "421373210afd132")
|
||||
}
|
||||
|
||||
func handleWait(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
if vars["id"] == "valid-id" {
|
||||
fmt.Fprintf(w, `{"StatusCode":0}`)
|
||||
} else {
|
||||
http.Error(w, "failed", 500)
|
||||
}
|
||||
}
|
||||
|
||||
func handleImagePull(w http.ResponseWriter, r *http.Request) {
|
||||
imageName := r.URL.Query()["fromImage"][0]
|
||||
responses := []map[string]interface{}{{
|
||||
"status": fmt.Sprintf("Pulling repository mydockerregistry/%s", imageName),
|
||||
}}
|
||||
switch imageName {
|
||||
case "busybox":
|
||||
responses = append(responses, map[string]interface{}{
|
||||
"status": "Status: Image is up to date for mydockerregistry/busybox",
|
||||
})
|
||||
case "haproxy":
|
||||
fmt.Fprintf(w, haproxyPullOutput)
|
||||
return
|
||||
default:
|
||||
errorMsg := fmt.Sprintf("Error: image %s not found", imageName)
|
||||
responses = append(responses, map[string]interface{}{
|
||||
"errorDetail": map[string]interface{}{
|
||||
"message": errorMsg,
|
||||
},
|
||||
"error": errorMsg,
|
||||
})
|
||||
}
|
||||
for _, response := range responses {
|
||||
json.NewEncoder(w).Encode(response)
|
||||
}
|
||||
}
|
||||
|
||||
func handleContainerLogs(w http.ResponseWriter, r *http.Request) {
|
||||
var outStream, errStream io.Writer
|
||||
outStream = ioutils.NewWriteFlusher(w)
|
||||
|
||||
// not sure how to test follow
|
||||
if err := r.ParseForm(); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
}
|
||||
stdout, stderr := getBoolValue(r.Form.Get("stdout")), getBoolValue(r.Form.Get("stderr"))
|
||||
if stderr {
|
||||
errStream = stdcopy.NewStdWriter(outStream, stdcopy.Stderr)
|
||||
}
|
||||
if stdout {
|
||||
outStream = stdcopy.NewStdWriter(outStream, stdcopy.Stdout)
|
||||
}
|
||||
var i int
|
||||
if tail, err := strconv.Atoi(r.Form.Get("tail")); err == nil && tail > 0 {
|
||||
i = 50 - tail
|
||||
if i < 0 {
|
||||
i = 0
|
||||
}
|
||||
}
|
||||
for ; i < 50; i++ {
|
||||
line := fmt.Sprintf("line %d", i)
|
||||
if getBoolValue(r.Form.Get("timestamps")) {
|
||||
l := &jsonlog.JSONLog{Log: line, Created: time.Now().UTC()}
|
||||
line = fmt.Sprintf("%s %s", l.Created.Format(timeutils.RFC3339NanoFixed), line)
|
||||
}
|
||||
if i%2 == 0 && stderr {
|
||||
fmt.Fprintln(errStream, line)
|
||||
} else if i%2 == 1 && stdout {
|
||||
fmt.Fprintln(outStream, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func handleContainerChanges(w http.ResponseWriter, r *http.Request) {
|
||||
writeHeaders(w, 200, "changes")
|
||||
body := `[
|
||||
{
|
||||
"Path": "/dev",
|
||||
"Kind": 0
|
||||
},
|
||||
{
|
||||
"Path": "/dev/kmsg",
|
||||
"Kind": 1
|
||||
},
|
||||
{
|
||||
"Path": "/test",
|
||||
"Kind": 1
|
||||
}
|
||||
]`
|
||||
w.Write([]byte(body))
|
||||
}
|
||||
|
||||
func getBoolValue(boolString string) bool {
|
||||
switch boolString {
|
||||
case "1":
|
||||
return true
|
||||
case "True":
|
||||
return true
|
||||
case "true":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func writeHeaders(w http.ResponseWriter, code int, jobName string) {
|
||||
h := w.Header()
|
||||
h.Add("Content-Type", "application/json")
|
||||
if jobName != "" {
|
||||
h.Add("Job-Name", jobName)
|
||||
}
|
||||
w.WriteHeader(code)
|
||||
}
|
||||
|
||||
func handlerGetInfo(w http.ResponseWriter, r *http.Request) {
|
||||
writeHeaders(w, 200, "info")
|
||||
body := `{
|
||||
"Containers": 2,
|
||||
"Debug": 1,
|
||||
"Driver": "aufs",
|
||||
"DriverStatus": [["Root Dir", "/mnt/sda1/var/lib/docker/aufs"],
|
||||
["Dirs", "0"]],
|
||||
"ExecutionDriver": "native-0.2",
|
||||
"IPv4Forwarding": 1,
|
||||
"Images": 1,
|
||||
"IndexServerAddress": "https://index.docker.io/v1/",
|
||||
"InitPath": "/usr/local/bin/docker",
|
||||
"InitSha1": "",
|
||||
"KernelVersion": "3.16.4-tinycore64",
|
||||
"MemoryLimit": 1,
|
||||
"NEventsListener": 0,
|
||||
"NFd": 10,
|
||||
"NGoroutines": 11,
|
||||
"OperatingSystem": "Boot2Docker 1.3.1 (TCL 5.4); master : a083df4 - Thu Jan 01 00:00:00 UTC 1970",
|
||||
"SwapLimit": 1}`
|
||||
w.Write([]byte(body))
|
||||
}
|
||||
|
||||
func handlerGetContainers(w http.ResponseWriter, r *http.Request) {
|
||||
writeHeaders(w, 200, "containers")
|
||||
body := `[
|
||||
{
|
||||
"Status": "Up 39 seconds",
|
||||
"Ports": [
|
||||
{
|
||||
"Type": "tcp",
|
||||
"PublicPort": 49163,
|
||||
"PrivatePort": 8080,
|
||||
"IP": "0.0.0.0"
|
||||
}
|
||||
],
|
||||
"Names": [
|
||||
"/trusting_heisenberg"
|
||||
],
|
||||
"Image": "foo:latest",
|
||||
"Id": "332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce",
|
||||
"Created": 1415720105,
|
||||
"Command": "/bin/go-run"
|
||||
}
|
||||
]`
|
||||
if v, ok := r.URL.Query()["size"]; ok {
|
||||
if v[0] == "1" {
|
||||
body = `[
|
||||
{
|
||||
"Status": "Up 39 seconds",
|
||||
"Ports": [
|
||||
{
|
||||
"Type": "tcp",
|
||||
"PublicPort": 49163,
|
||||
"PrivatePort": 8080,
|
||||
"IP": "0.0.0.0"
|
||||
}
|
||||
],
|
||||
"Names": [
|
||||
"/trusting_heisenberg"
|
||||
],
|
||||
"Image": "foo:latest",
|
||||
"Id": "332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce",
|
||||
"Created": 1415720105,
|
||||
"SizeRootFs": 12345,
|
||||
"SizeRW": 123,
|
||||
"Command": "/bin/go-run"
|
||||
}
|
||||
]`
|
||||
}
|
||||
}
|
||||
if v, ok := r.URL.Query()["filters"]; ok {
|
||||
if v[0] != "{'id':['332375cfbc23edb921a21026314c3497674ba8bdcb2c85e0e65ebf2017f688ce']}" {
|
||||
body = "[]"
|
||||
}
|
||||
}
|
||||
w.Write([]byte(body))
|
||||
}
|
||||
|
||||
func handleEvents(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(eventsResp))
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package mockclient
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/samalba/dockerclient"
|
||||
)
|
||||
|
||||
func TestMock(t *testing.T) {
|
||||
mock := NewMockClient()
|
||||
mock.On("Version").Return(&dockerclient.Version{Version: "foo"}, nil).Once()
|
||||
|
||||
v, err := mock.Version()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v.Version != "foo" {
|
||||
t.Fatal(v)
|
||||
}
|
||||
|
||||
mock.Mock.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestMockInterface(t *testing.T) {
|
||||
iface := reflect.TypeOf((*dockerclient.Client)(nil)).Elem()
|
||||
mock := NewMockClient()
|
||||
|
||||
if !reflect.TypeOf(mock).Implements(iface) {
|
||||
t.Fatalf("Mock does not implement the Client interface")
|
||||
}
|
||||
}
|
|
@ -41,6 +41,12 @@ function teardown() {
|
|||
--device=/dev/loop0:/dev/loop0 \
|
||||
--ipc=host \
|
||||
--pid=host \
|
||||
--memory-swappiness=2 \
|
||||
--group-add="root" \
|
||||
--memory-reservation=100 \
|
||||
--kernel-memory=100 \
|
||||
--dns-opt="someDnsOption" \
|
||||
--stop-signal="SIGKILL" \
|
||||
busybox sleep 1000
|
||||
|
||||
# verify, container is running
|
||||
|
@ -65,6 +71,18 @@ function teardown() {
|
|||
[[ "${output}" == *"\"IpcMode\": \"host\""* ]]
|
||||
# pid
|
||||
[[ "${output}" == *"\"PidMode\": \"host\""* ]]
|
||||
# memory-swappiness
|
||||
[[ "${output}" == *"\"MemorySwappiness\": 2"* ]]
|
||||
# group-add
|
||||
[[ "${output}" == *"root"* ]]
|
||||
# memory-reservation
|
||||
[[ "${output}" == *"\"MemoryReservation\": 100"* ]]
|
||||
# kernel-memory
|
||||
[[ "${output}" == *"\"KernelMemory\": 100"* ]]
|
||||
# dns-opt
|
||||
[[ "${output}" == *"someDnsOption"* ]]
|
||||
# stop-signal
|
||||
[[ "${output}" == *"\"StopSignal\": \"SIGKILL\""* ]]
|
||||
}
|
||||
|
||||
@test "docker run - reschedule with soft-image-affinity" {
|
||||
|
|
Loading…
Reference in New Issue