Merge pull request #4901 from vieux/split_api_2_pkg

Split API into 2 go packages
This commit is contained in:
unclejack 2014-03-31 21:32:05 +03:00
commit 1805ef1ccc
12 changed files with 669 additions and 614 deletions

View file

@ -1,9 +1,6 @@
package api
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
)
@ -20,46 +17,3 @@ func TestJsonContentType(t *testing.T) {
t.Fail()
}
}
func TestGetBoolParam(t *testing.T) {
if ret, err := getBoolParam("true"); err != nil || !ret {
t.Fatalf("true -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("True"); err != nil || !ret {
t.Fatalf("True -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("1"); err != nil || !ret {
t.Fatalf("1 -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam(""); err != nil || ret {
t.Fatalf("\"\" -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("false"); err != nil || ret {
t.Fatalf("false -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("0"); err != nil || ret {
t.Fatalf("0 -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("faux"); err == nil || ret {
t.Fatalf("faux -> false, err | got %t %s", ret, err)
}
}
func TesthttpError(t *testing.T) {
r := httptest.NewRecorder()
httpError(r, fmt.Errorf("No such method"))
if r.Code != http.StatusNotFound {
t.Fatalf("Expected %d, got %d", http.StatusNotFound, r.Code)
}
httpError(r, fmt.Errorf("This accound hasn't been activated"))
if r.Code != http.StatusForbidden {
t.Fatalf("Expected %d, got %d", http.StatusForbidden, r.Code)
}
httpError(r, fmt.Errorf("Some error"))
if r.Code != http.StatusInternalServerError {
t.Fatalf("Expected %d, got %d", http.StatusInternalServerError, r.Code)
}
}

102
api/client/cli.go Normal file
View file

@ -0,0 +1,102 @@
package client
import (
"crypto/tls"
"encoding/json"
"fmt"
"io"
"os"
"reflect"
"strings"
"text/template"
flag "github.com/dotcloud/docker/pkg/mflag"
"github.com/dotcloud/docker/pkg/term"
"github.com/dotcloud/docker/registry"
)
var funcMap = template.FuncMap{
"json": func(v interface{}) string {
a, _ := json.Marshal(v)
return string(a)
},
}
func (cli *DockerCli) getMethod(name string) (func(...string) error, bool) {
methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:])
method := reflect.ValueOf(cli).MethodByName(methodName)
if !method.IsValid() {
return nil, false
}
return method.Interface().(func(...string) error), true
}
func (cli *DockerCli) ParseCommands(args ...string) error {
if len(args) > 0 {
method, exists := cli.getMethod(args[0])
if !exists {
fmt.Println("Error: Command not found:", args[0])
return cli.CmdHelp(args[1:]...)
}
return method(args[1:]...)
}
return cli.CmdHelp(args...)
}
func (cli *DockerCli) Subcmd(name, signature, description string) *flag.FlagSet {
flags := flag.NewFlagSet(name, flag.ContinueOnError)
flags.Usage = func() {
fmt.Fprintf(cli.err, "\nUsage: docker %s %s\n\n%s\n\n", name, signature, description)
flags.PrintDefaults()
os.Exit(2)
}
return flags
}
func (cli *DockerCli) LoadConfigFile() (err error) {
cli.configFile, err = registry.LoadConfig(os.Getenv("HOME"))
if err != nil {
fmt.Fprintf(cli.err, "WARNING: %s\n", err)
}
return err
}
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var (
isTerminal = false
terminalFd uintptr
)
if in != nil {
if file, ok := in.(*os.File); ok {
terminalFd = file.Fd()
isTerminal = term.IsTerminal(terminalFd)
}
}
if err == nil {
err = out
}
return &DockerCli{
proto: proto,
addr: addr,
in: in,
out: out,
err: err,
isTerminal: isTerminal,
terminalFd: terminalFd,
tlsConfig: tlsConfig,
}
}
type DockerCli struct {
proto string
addr string
configFile *registry.ConfigFile
in io.ReadCloser
out io.Writer
err io.Writer
isTerminal bool
terminalFd uintptr
tlsConfig *tls.Config
}

View file

@ -1,35 +1,18 @@
package api
package client
import (
"bufio"
"bytes"
"crypto/tls"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/dockerversion"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/nat"
flag "github.com/dotcloud/docker/pkg/mflag"
"github.com/dotcloud/docker/pkg/signal"
"github.com/dotcloud/docker/pkg/term"
"github.com/dotcloud/docker/registry"
"github.com/dotcloud/docker/runconfig"
"github.com/dotcloud/docker/utils"
"io"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"os/exec"
gosignal "os/signal"
"path"
"reflect"
"regexp"
goruntime "runtime"
"strconv"
"strings"
@ -37,40 +20,19 @@ import (
"text/tabwriter"
"text/template"
"time"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/archive"
"github.com/dotcloud/docker/dockerversion"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/nat"
"github.com/dotcloud/docker/pkg/signal"
"github.com/dotcloud/docker/pkg/term"
"github.com/dotcloud/docker/registry"
"github.com/dotcloud/docker/runconfig"
"github.com/dotcloud/docker/utils"
)
var funcMap = template.FuncMap{
"json": func(v interface{}) string {
a, _ := json.Marshal(v)
return string(a)
},
}
var (
ErrConnectionRefused = errors.New("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
)
func (cli *DockerCli) getMethod(name string) (func(...string) error, bool) {
methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:])
method := reflect.ValueOf(cli).MethodByName(methodName)
if !method.IsValid() {
return nil, false
}
return method.Interface().(func(...string) error), true
}
func (cli *DockerCli) ParseCommands(args ...string) error {
if len(args) > 0 {
method, exists := cli.getMethod(args[0])
if !exists {
fmt.Println("Error: Command not found:", args[0])
return cli.CmdHelp(args[1:]...)
}
return method(args[1:]...)
}
return cli.CmdHelp(args...)
}
func (cli *DockerCli) CmdHelp(args ...string) error {
if len(args) > 0 {
method, exists := cli.getMethod(args[0])
@ -81,7 +43,7 @@ func (cli *DockerCli) CmdHelp(args ...string) error {
return nil
}
}
help := fmt.Sprintf("Usage: docker [OPTIONS] COMMAND [arg...]\n -H=[unix://%s]: tcp://host:port to bind/connect to or unix://path/to/socket to use\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n", DEFAULTUNIXSOCKET)
help := fmt.Sprintf("Usage: docker [OPTIONS] COMMAND [arg...]\n -H=[unix://%s]: tcp://host:port to bind/connect to or unix://path/to/socket to use\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n", api.DEFAULTUNIXSOCKET)
for _, command := range [][]string{
{"attach", "Attach to a running container"},
{"build", "Build a container from a Dockerfile"},
@ -610,7 +572,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
return err
}
container := &Container{}
container := &api.Container{}
err = json.Unmarshal(body, container)
if err != nil {
return err
@ -797,9 +759,13 @@ func (cli *DockerCli) CmdPort(args ...string) error {
return nil
}
port := cmd.Arg(1)
proto := "tcp"
parts := strings.SplitN(port, "/", 2)
var (
port = cmd.Arg(1)
proto = "tcp"
parts = strings.SplitN(port, "/", 2)
container api.Container
)
if len(parts) == 2 && len(parts[1]) != 0 {
port = parts[0]
proto = parts[1]
@ -808,13 +774,13 @@ func (cli *DockerCli) CmdPort(args ...string) error {
if err != nil {
return err
}
var out Container
err = json.Unmarshal(body, &out)
err = json.Unmarshal(body, &container)
if err != nil {
return err
}
if frontends, exists := out.NetworkSettings.Ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
if frontends, exists := container.NetworkSettings.Ports[nat.Port(port+"/"+proto)]; exists && frontends != nil {
for _, frontend := range frontends {
fmt.Fprintf(cli.out, "%s:%s\n", frontend.HostIp, frontend.HostPort)
}
@ -1425,7 +1391,7 @@ func (cli *DockerCli) CmdPs(args ...string) error {
outCommand = utils.Trunc(outCommand, 20)
}
ports.ReadListFrom([]byte(out.Get("Ports")))
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", outID, out.Get("Image"), outCommand, utils.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), out.Get("Status"), displayablePorts(ports), strings.Join(outNames, ","))
fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\t%s\t", outID, out.Get("Image"), outCommand, utils.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), out.Get("Status"), api.DisplayablePorts(ports), strings.Join(outNames, ","))
if *size {
if out.GetInt("SizeRootFs") > 0 {
fmt.Fprintf(w, "%s (virtual %s)\n", utils.HumanSize(out.GetInt64("SizeRw")), utils.HumanSize(out.GetInt64("SizeRootFs")))
@ -1606,7 +1572,7 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
return err
}
container := &Container{}
container := &api.Container{}
err = json.Unmarshal(body, container)
if err != nil {
return err
@ -1643,7 +1609,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
return err
}
container := &Container{}
container := &api.Container{}
err = json.Unmarshal(body, container)
if err != nil {
return err
@ -2130,417 +2096,3 @@ func (cli *DockerCli) CmdLoad(args ...string) error {
}
return nil
}
func (cli *DockerCli) dial() (net.Conn, error) {
if cli.tlsConfig != nil && cli.proto != "unix" {
return tls.Dial(cli.proto, cli.addr, cli.tlsConfig)
}
return net.Dial(cli.proto, cli.addr)
}
func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo bool) (io.ReadCloser, int, error) {
params := bytes.NewBuffer(nil)
if data != nil {
if env, ok := data.(engine.Env); ok {
if err := env.Encode(params); err != nil {
return nil, -1, err
}
} else {
buf, err := json.Marshal(data)
if err != nil {
return nil, -1, err
}
if _, err := params.Write(buf); err != nil {
return nil, -1, err
}
}
}
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", APIVERSION, path), params)
if err != nil {
return nil, -1, err
}
if passAuthInfo {
cli.LoadConfigFile()
// Resolve the Auth config relevant for this server
authConfig := cli.configFile.ResolveAuthConfig(registry.IndexServerAddress())
getHeaders := func(authConfig registry.AuthConfig) (map[string][]string, error) {
buf, err := json.Marshal(authConfig)
if err != nil {
return nil, err
}
registryAuthHeader := []string{
base64.URLEncoding.EncodeToString(buf),
}
return map[string][]string{"X-Registry-Auth": registryAuthHeader}, nil
}
if headers, err := getHeaders(authConfig); err == nil && headers != nil {
for k, v := range headers {
req.Header[k] = v
}
}
}
req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
req.Host = cli.addr
if data != nil {
req.Header.Set("Content-Type", "application/json")
} else if method == "POST" {
req.Header.Set("Content-Type", "plain/text")
}
dial, err := cli.dial()
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return nil, -1, ErrConnectionRefused
}
return nil, -1, err
}
clientconn := httputil.NewClientConn(dial, nil)
resp, err := clientconn.Do(req)
if err != nil {
clientconn.Close()
if strings.Contains(err.Error(), "connection refused") {
return nil, -1, ErrConnectionRefused
}
return nil, -1, err
}
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, -1, err
}
if len(body) == 0 {
return nil, resp.StatusCode, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(resp.StatusCode), req.URL)
}
return nil, resp.StatusCode, fmt.Errorf("Error: %s", bytes.TrimSpace(body))
}
wrapper := utils.NewReadCloserWrapper(resp.Body, func() error {
if resp != nil && resp.Body != nil {
resp.Body.Close()
}
return clientconn.Close()
})
return wrapper, resp.StatusCode, nil
}
func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, headers map[string][]string) error {
if (method == "POST" || method == "PUT") && in == nil {
in = bytes.NewReader([]byte{})
}
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", APIVERSION, path), in)
if err != nil {
return err
}
req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
req.Host = cli.addr
if method == "POST" {
req.Header.Set("Content-Type", "plain/text")
}
if headers != nil {
for k, v := range headers {
req.Header[k] = v
}
}
dial, err := cli.dial()
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
}
return err
}
clientconn := httputil.NewClientConn(dial, nil)
resp, err := clientconn.Do(req)
defer clientconn.Close()
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
}
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
if len(body) == 0 {
return fmt.Errorf("Error :%s", http.StatusText(resp.StatusCode))
}
return fmt.Errorf("Error: %s", bytes.TrimSpace(body))
}
if MatchesContentType(resp.Header.Get("Content-Type"), "application/json") {
return utils.DisplayJSONMessagesStream(resp.Body, out, cli.terminalFd, cli.isTerminal)
}
if _, err := io.Copy(out, resp.Body); err != nil {
return err
}
return nil
}
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer, started chan io.Closer) error {
defer func() {
if started != nil {
close(started)
}
}()
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", APIVERSION, path), nil)
if err != nil {
return err
}
req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
req.Header.Set("Content-Type", "plain/text")
req.Host = cli.addr
dial, err := cli.dial()
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
}
return err
}
clientconn := httputil.NewClientConn(dial, nil)
defer clientconn.Close()
// Server hijacks the connection, error 'connection closed' expected
clientconn.Do(req)
rwc, br := clientconn.Hijack()
defer rwc.Close()
if started != nil {
started <- rwc
}
var receiveStdout chan error
var oldState *term.State
if in != nil && setRawTerminal && cli.isTerminal && os.Getenv("NORAW") == "" {
oldState, err = term.SetRawTerminal(cli.terminalFd)
if err != nil {
return err
}
defer term.RestoreTerminal(cli.terminalFd, oldState)
}
if stdout != nil || stderr != nil {
receiveStdout = utils.Go(func() (err error) {
defer func() {
if in != nil {
if setRawTerminal && cli.isTerminal {
term.RestoreTerminal(cli.terminalFd, oldState)
}
// For some reason this Close call blocks on darwin..
// As the client exists right after, simply discard the close
// until we find a better solution.
if goruntime.GOOS != "darwin" {
in.Close()
}
}
}()
// When TTY is ON, use regular copy
if setRawTerminal {
_, err = io.Copy(stdout, br)
} else {
_, err = utils.StdCopy(stdout, stderr, br)
}
utils.Debugf("[hijack] End of stdout")
return err
})
}
sendStdin := utils.Go(func() error {
if in != nil {
io.Copy(rwc, in)
utils.Debugf("[hijack] End of stdin")
}
if tcpc, ok := rwc.(*net.TCPConn); ok {
if err := tcpc.CloseWrite(); err != nil {
utils.Debugf("Couldn't send EOF: %s\n", err)
}
} else if unixc, ok := rwc.(*net.UnixConn); ok {
if err := unixc.CloseWrite(); err != nil {
utils.Debugf("Couldn't send EOF: %s\n", err)
}
}
// Discard errors due to pipe interruption
return nil
})
if stdout != nil || stderr != nil {
if err := <-receiveStdout; err != nil {
utils.Debugf("Error receiveStdout: %s", err)
return err
}
}
if !cli.isTerminal {
if err := <-sendStdin; err != nil {
utils.Debugf("Error sendStdin: %s", err)
return err
}
}
return nil
}
func (cli *DockerCli) getTtySize() (int, int) {
if !cli.isTerminal {
return 0, 0
}
ws, err := term.GetWinsize(cli.terminalFd)
if err != nil {
utils.Debugf("Error getting size: %s", err)
if ws == nil {
return 0, 0
}
}
return int(ws.Height), int(ws.Width)
}
func (cli *DockerCli) resizeTty(id string) {
height, width := cli.getTtySize()
if height == 0 && width == 0 {
return
}
v := url.Values{}
v.Set("h", strconv.Itoa(height))
v.Set("w", strconv.Itoa(width))
if _, _, err := readBody(cli.call("POST", "/containers/"+id+"/resize?"+v.Encode(), nil, false)); err != nil {
utils.Debugf("Error resize: %s", err)
}
}
func (cli *DockerCli) monitorTtySize(id string) error {
cli.resizeTty(id)
sigchan := make(chan os.Signal, 1)
gosignal.Notify(sigchan, syscall.SIGWINCH)
go func() {
for _ = range sigchan {
cli.resizeTty(id)
}
}()
return nil
}
func (cli *DockerCli) Subcmd(name, signature, description string) *flag.FlagSet {
flags := flag.NewFlagSet(name, flag.ContinueOnError)
flags.Usage = func() {
fmt.Fprintf(cli.err, "\nUsage: docker %s %s\n\n%s\n\n", name, signature, description)
flags.PrintDefaults()
os.Exit(2)
}
return flags
}
func (cli *DockerCli) LoadConfigFile() (err error) {
cli.configFile, err = registry.LoadConfig(os.Getenv("HOME"))
if err != nil {
fmt.Fprintf(cli.err, "WARNING: %s\n", err)
}
return err
}
func waitForExit(cli *DockerCli, containerId string) (int, error) {
stream, _, err := cli.call("POST", "/containers/"+containerId+"/wait", nil, false)
if err != nil {
return -1, err
}
var out engine.Env
if err := out.Decode(stream); err != nil {
return -1, err
}
return out.GetInt("StatusCode"), nil
}
// getExitCode perform an inspect on the container. It returns
// the running state and the exit code.
func getExitCode(cli *DockerCli, containerId string) (bool, int, error) {
body, _, err := readBody(cli.call("GET", "/containers/"+containerId+"/json", nil, false))
if err != nil {
// If we can't connect, then the daemon probably died.
if err != ErrConnectionRefused {
return false, -1, err
}
return false, -1, nil
}
c := &Container{}
if err := json.Unmarshal(body, c); err != nil {
return false, -1, err
}
return c.State.Running, c.State.ExitCode, nil
}
func readBody(stream io.ReadCloser, statusCode int, err error) ([]byte, int, error) {
if stream != nil {
defer stream.Close()
}
if err != nil {
return nil, statusCode, err
}
body, err := ioutil.ReadAll(stream)
if err != nil {
return nil, -1, err
}
return body, statusCode, nil
}
func NewDockerCli(in io.ReadCloser, out, err io.Writer, proto, addr string, tlsConfig *tls.Config) *DockerCli {
var (
isTerminal = false
terminalFd uintptr
)
if in != nil {
if file, ok := in.(*os.File); ok {
terminalFd = file.Fd()
isTerminal = term.IsTerminal(terminalFd)
}
}
if err == nil {
err = out
}
return &DockerCli{
proto: proto,
addr: addr,
in: in,
out: out,
err: err,
isTerminal: isTerminal,
terminalFd: terminalFd,
tlsConfig: tlsConfig,
}
}
type DockerCli struct {
proto string
addr string
configFile *registry.ConfigFile
in io.ReadCloser
out io.Writer
err io.Writer
isTerminal bool
terminalFd uintptr
tlsConfig *tls.Config
}

390
api/client/utils.go Normal file
View file

@ -0,0 +1,390 @@
package client
import (
"bytes"
"crypto/tls"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
gosignal "os/signal"
"regexp"
goruntime "runtime"
"strconv"
"strings"
"syscall"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/dockerversion"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/pkg/term"
"github.com/dotcloud/docker/registry"
"github.com/dotcloud/docker/utils"
)
var (
ErrConnectionRefused = errors.New("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
)
func (cli *DockerCli) dial() (net.Conn, error) {
if cli.tlsConfig != nil && cli.proto != "unix" {
return tls.Dial(cli.proto, cli.addr, cli.tlsConfig)
}
return net.Dial(cli.proto, cli.addr)
}
func (cli *DockerCli) call(method, path string, data interface{}, passAuthInfo bool) (io.ReadCloser, int, error) {
params := bytes.NewBuffer(nil)
if data != nil {
if env, ok := data.(engine.Env); ok {
if err := env.Encode(params); err != nil {
return nil, -1, err
}
} else {
buf, err := json.Marshal(data)
if err != nil {
return nil, -1, err
}
if _, err := params.Write(buf); err != nil {
return nil, -1, err
}
}
}
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), params)
if err != nil {
return nil, -1, err
}
if passAuthInfo {
cli.LoadConfigFile()
// Resolve the Auth config relevant for this server
authConfig := cli.configFile.ResolveAuthConfig(registry.IndexServerAddress())
getHeaders := func(authConfig registry.AuthConfig) (map[string][]string, error) {
buf, err := json.Marshal(authConfig)
if err != nil {
return nil, err
}
registryAuthHeader := []string{
base64.URLEncoding.EncodeToString(buf),
}
return map[string][]string{"X-Registry-Auth": registryAuthHeader}, nil
}
if headers, err := getHeaders(authConfig); err == nil && headers != nil {
for k, v := range headers {
req.Header[k] = v
}
}
}
req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
req.Host = cli.addr
if data != nil {
req.Header.Set("Content-Type", "application/json")
} else if method == "POST" {
req.Header.Set("Content-Type", "plain/text")
}
dial, err := cli.dial()
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return nil, -1, ErrConnectionRefused
}
return nil, -1, err
}
clientconn := httputil.NewClientConn(dial, nil)
resp, err := clientconn.Do(req)
if err != nil {
clientconn.Close()
if strings.Contains(err.Error(), "connection refused") {
return nil, -1, ErrConnectionRefused
}
return nil, -1, err
}
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, -1, err
}
if len(body) == 0 {
return nil, resp.StatusCode, fmt.Errorf("Error: request returned %s for API route and version %s, check if the server supports the requested API version", http.StatusText(resp.StatusCode), req.URL)
}
return nil, resp.StatusCode, fmt.Errorf("Error: %s", bytes.TrimSpace(body))
}
wrapper := utils.NewReadCloserWrapper(resp.Body, func() error {
if resp != nil && resp.Body != nil {
resp.Body.Close()
}
return clientconn.Close()
})
return wrapper, resp.StatusCode, nil
}
func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer, headers map[string][]string) error {
if (method == "POST" || method == "PUT") && in == nil {
in = bytes.NewReader([]byte{})
}
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), in)
if err != nil {
return err
}
req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
req.Host = cli.addr
if method == "POST" {
req.Header.Set("Content-Type", "plain/text")
}
if headers != nil {
for k, v := range headers {
req.Header[k] = v
}
}
dial, err := cli.dial()
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
}
return err
}
clientconn := httputil.NewClientConn(dial, nil)
resp, err := clientconn.Do(req)
defer clientconn.Close()
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
}
return err
}
defer resp.Body.Close()
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
if len(body) == 0 {
return fmt.Errorf("Error :%s", http.StatusText(resp.StatusCode))
}
return fmt.Errorf("Error: %s", bytes.TrimSpace(body))
}
if api.MatchesContentType(resp.Header.Get("Content-Type"), "application/json") {
return utils.DisplayJSONMessagesStream(resp.Body, out, cli.terminalFd, cli.isTerminal)
}
if _, err := io.Copy(out, resp.Body); err != nil {
return err
}
return nil
}
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.ReadCloser, stdout, stderr io.Writer, started chan io.Closer) error {
defer func() {
if started != nil {
close(started)
}
}()
// fixme: refactor client to support redirect
re := regexp.MustCompile("/+")
path = re.ReplaceAllString(path, "/")
req, err := http.NewRequest(method, fmt.Sprintf("/v%s%s", api.APIVERSION, path), nil)
if err != nil {
return err
}
req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
req.Header.Set("Content-Type", "plain/text")
req.Host = cli.addr
dial, err := cli.dial()
if err != nil {
if strings.Contains(err.Error(), "connection refused") {
return fmt.Errorf("Cannot connect to the Docker daemon. Is 'docker -d' running on this host?")
}
return err
}
clientconn := httputil.NewClientConn(dial, nil)
defer clientconn.Close()
// Server hijacks the connection, error 'connection closed' expected
clientconn.Do(req)
rwc, br := clientconn.Hijack()
defer rwc.Close()
if started != nil {
started <- rwc
}
var receiveStdout chan error
var oldState *term.State
if in != nil && setRawTerminal && cli.isTerminal && os.Getenv("NORAW") == "" {
oldState, err = term.SetRawTerminal(cli.terminalFd)
if err != nil {
return err
}
defer term.RestoreTerminal(cli.terminalFd, oldState)
}
if stdout != nil || stderr != nil {
receiveStdout = utils.Go(func() (err error) {
defer func() {
if in != nil {
if setRawTerminal && cli.isTerminal {
term.RestoreTerminal(cli.terminalFd, oldState)
}
// For some reason this Close call blocks on darwin..
// As the client exists right after, simply discard the close
// until we find a better solution.
if goruntime.GOOS != "darwin" {
in.Close()
}
}
}()
// When TTY is ON, use regular copy
if setRawTerminal {
_, err = io.Copy(stdout, br)
} else {
_, err = utils.StdCopy(stdout, stderr, br)
}
utils.Debugf("[hijack] End of stdout")
return err
})
}
sendStdin := utils.Go(func() error {
if in != nil {
io.Copy(rwc, in)
utils.Debugf("[hijack] End of stdin")
}
if tcpc, ok := rwc.(*net.TCPConn); ok {
if err := tcpc.CloseWrite(); err != nil {
utils.Debugf("Couldn't send EOF: %s\n", err)
}
} else if unixc, ok := rwc.(*net.UnixConn); ok {
if err := unixc.CloseWrite(); err != nil {
utils.Debugf("Couldn't send EOF: %s\n", err)
}
}
// Discard errors due to pipe interruption
return nil
})
if stdout != nil || stderr != nil {
if err := <-receiveStdout; err != nil {
utils.Debugf("Error receiveStdout: %s", err)
return err
}
}
if !cli.isTerminal {
if err := <-sendStdin; err != nil {
utils.Debugf("Error sendStdin: %s", err)
return err
}
}
return nil
}
func (cli *DockerCli) resizeTty(id string) {
height, width := cli.getTtySize()
if height == 0 && width == 0 {
return
}
v := url.Values{}
v.Set("h", strconv.Itoa(height))
v.Set("w", strconv.Itoa(width))
if _, _, err := readBody(cli.call("POST", "/containers/"+id+"/resize?"+v.Encode(), nil, false)); err != nil {
utils.Debugf("Error resize: %s", err)
}
}
func waitForExit(cli *DockerCli, containerId string) (int, error) {
stream, _, err := cli.call("POST", "/containers/"+containerId+"/wait", nil, false)
if err != nil {
return -1, err
}
var out engine.Env
if err := out.Decode(stream); err != nil {
return -1, err
}
return out.GetInt("StatusCode"), nil
}
// getExitCode perform an inspect on the container. It returns
// the running state and the exit code.
func getExitCode(cli *DockerCli, containerId string) (bool, int, error) {
body, _, err := readBody(cli.call("GET", "/containers/"+containerId+"/json", nil, false))
if err != nil {
// If we can't connect, then the daemon probably died.
if err != ErrConnectionRefused {
return false, -1, err
}
return false, -1, nil
}
c := &api.Container{}
if err := json.Unmarshal(body, c); err != nil {
return false, -1, err
}
return c.State.Running, c.State.ExitCode, nil
}
func (cli *DockerCli) monitorTtySize(id string) error {
cli.resizeTty(id)
sigchan := make(chan os.Signal, 1)
gosignal.Notify(sigchan, syscall.SIGWINCH)
go func() {
for _ = range sigchan {
cli.resizeTty(id)
}
}()
return nil
}
func (cli *DockerCli) getTtySize() (int, int) {
if !cli.isTerminal {
return 0, 0
}
ws, err := term.GetWinsize(cli.terminalFd)
if err != nil {
utils.Debugf("Error getting size: %s", err)
if ws == nil {
return 0, 0
}
}
return int(ws.Height), int(ws.Width)
}
func readBody(stream io.ReadCloser, statusCode int, err error) ([]byte, int, error) {
if stream != nil {
defer stream.Close()
}
if err != nil {
return nil, statusCode, err
}
body, err := ioutil.ReadAll(stream)
if err != nil {
return nil, -1, err
}
return body, statusCode, nil
}

View file

@ -23,7 +23,7 @@ func ValidateHost(val string) (string, error) {
}
//TODO remove, used on < 1.5 in getContainersJSON
func displayablePorts(ports *engine.Table) string {
func DisplayablePorts(ports *engine.Table) string {
result := []string{}
ports.SetKey("PublicPort")
ports.Sort()

View file

@ -1,4 +1,4 @@
package api
package server
import (
"bufio"
@ -10,14 +10,6 @@ import (
"encoding/json"
"expvar"
"fmt"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/pkg/listenbuffer"
"github.com/dotcloud/docker/pkg/systemd"
"github.com/dotcloud/docker/pkg/user"
"github.com/dotcloud/docker/pkg/version"
"github.com/dotcloud/docker/registry"
"github.com/dotcloud/docker/utils"
"github.com/gorilla/mux"
"io"
"io/ioutil"
"log"
@ -28,6 +20,16 @@ import (
"strconv"
"strings"
"syscall"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/pkg/listenbuffer"
"github.com/dotcloud/docker/pkg/systemd"
"github.com/dotcloud/docker/pkg/user"
"github.com/dotcloud/docker/pkg/version"
"github.com/dotcloud/docker/registry"
"github.com/dotcloud/docker/utils"
"github.com/gorilla/mux"
)
var (
@ -315,7 +317,7 @@ func getContainersJSON(eng *engine.Engine, version version.Version, w http.Respo
for _, out := range outs.Data {
ports := engine.NewTable("", 0)
ports.ReadListFrom([]byte(out.Get("Ports")))
out.Set("Ports", displayablePorts(ports))
out.Set("Ports", api.DisplayablePorts(ports))
}
w.Header().Set("Content-Type", "application/json")
if _, err = outs.WriteListTo(w); err != nil {
@ -638,7 +640,7 @@ func postContainersStart(eng *engine.Engine, version version.Version, w http.Res
job := eng.Job("start", name)
// allow a nil body for backwards compatibility
if r.Body != nil {
if MatchesContentType(r.Header.Get("Content-Type"), "application/json") {
if api.MatchesContentType(r.Header.Get("Content-Type"), "application/json") {
if err := job.DecodeEnv(r.Body); err != nil {
return err
}
@ -885,7 +887,7 @@ func postContainersCopy(eng *engine.Engine, version version.Version, w http.Resp
var copyData engine.Env
if contentType := r.Header.Get("Content-Type"); MatchesContentType(contentType, "application/json") {
if contentType := r.Header.Get("Content-Type"); api.MatchesContentType(contentType, "application/json") {
if err := copyData.Decode(r.Body); err != nil {
return err
}
@ -943,14 +945,14 @@ func makeHttpHandler(eng *engine.Engine, logging bool, localMethod string, local
}
version := version.Version(mux.Vars(r)["version"])
if version == "" {
version = APIVERSION
version = api.APIVERSION
}
if enableCors {
writeCorsHeaders(w, r)
}
if version.GreaterThan(APIVERSION) {
http.Error(w, fmt.Errorf("client and server don't have same version (client : %s, server: %s)", version, APIVERSION).Error(), http.StatusNotFound)
if version.GreaterThan(api.APIVERSION) {
http.Error(w, fmt.Errorf("client and server don't have same version (client : %s, server: %s)", version, api.APIVERSION).Error(), http.StatusNotFound)
return
}

View file

@ -0,0 +1,52 @@
package server
import (
"fmt"
"net/http"
"net/http/httptest"
"testing"
)
func TestGetBoolParam(t *testing.T) {
if ret, err := getBoolParam("true"); err != nil || !ret {
t.Fatalf("true -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("True"); err != nil || !ret {
t.Fatalf("True -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("1"); err != nil || !ret {
t.Fatalf("1 -> true, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam(""); err != nil || ret {
t.Fatalf("\"\" -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("false"); err != nil || ret {
t.Fatalf("false -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("0"); err != nil || ret {
t.Fatalf("0 -> false, nil | got %t %s", ret, err)
}
if ret, err := getBoolParam("faux"); err == nil || ret {
t.Fatalf("faux -> false, err | got %t %s", ret, err)
}
}
func TesthttpError(t *testing.T) {
r := httptest.NewRecorder()
httpError(r, fmt.Errorf("No such method"))
if r.Code != http.StatusNotFound {
t.Fatalf("Expected %d, got %d", http.StatusNotFound, r.Code)
}
httpError(r, fmt.Errorf("This accound hasn't been activated"))
if r.Code != http.StatusForbidden {
t.Fatalf("Expected %d, got %d", http.StatusForbidden, r.Code)
}
httpError(r, fmt.Errorf("Some error"))
if r.Code != http.StatusInternalServerError {
t.Fatalf("Expected %d, got %d", http.StatusInternalServerError, r.Code)
}
}

View file

@ -1,7 +1,7 @@
package builtins
import (
"github.com/dotcloud/docker/api"
api "github.com/dotcloud/docker/api/server"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/runtime/networkdriver/bridge"
"github.com/dotcloud/docker/server"

View file

@ -10,6 +10,7 @@ import (
"strings"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/api/client"
"github.com/dotcloud/docker/builtins"
"github.com/dotcloud/docker/dockerversion"
"github.com/dotcloud/docker/engine"
@ -178,7 +179,7 @@ func main() {
protoAddrParts := strings.SplitN(flHosts.GetAll()[0], "://", 2)
var (
cli *api.DockerCli
cli *client.DockerCli
tlsConfig tls.Config
)
tlsConfig.InsecureSkipVerify = true
@ -211,9 +212,9 @@ func main() {
}
if *flTls || *flTlsVerify {
cli = api.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], &tlsConfig)
} else {
cli = api.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], nil)
cli = client.NewDockerCli(os.Stdin, os.Stdout, os.Stderr, protoAddrParts[0], protoAddrParts[1], nil)
}
if err := cli.ParseCommands(flag.Args()...); err != nil {

View file

@ -5,14 +5,6 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/dockerversion"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/image"
"github.com/dotcloud/docker/runconfig"
"github.com/dotcloud/docker/runtime"
"github.com/dotcloud/docker/utils"
"github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
"io"
"io/ioutil"
"net"
@ -21,6 +13,16 @@ import (
"strings"
"testing"
"time"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/api/server"
"github.com/dotcloud/docker/dockerversion"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/image"
"github.com/dotcloud/docker/runconfig"
"github.com/dotcloud/docker/runtime"
"github.com/dotcloud/docker/utils"
"github.com/dotcloud/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
)
func TestGetVersion(t *testing.T) {
@ -35,7 +37,7 @@ func TestGetVersion(t *testing.T) {
t.Fatal(err)
}
// FIXME getting the version should require an actual running Server
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -77,7 +79,7 @@ func TestGetInfo(t *testing.T) {
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -125,7 +127,7 @@ func TestGetEvents(t *testing.T) {
r := httptest.NewRecorder()
setTimeout(t, "", 500*time.Millisecond, func() {
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -166,7 +168,7 @@ func TestGetImagesJSON(t *testing.T) {
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -201,7 +203,7 @@ func TestGetImagesJSON(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
t.Fatal(err)
}
assertHttpNotError(r2, t)
@ -234,7 +236,7 @@ func TestGetImagesJSON(t *testing.T) {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r3, req3); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r3, req3); err != nil {
t.Fatal(err)
}
assertHttpNotError(r3, t)
@ -259,7 +261,7 @@ func TestGetImagesHistory(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -283,7 +285,7 @@ func TestGetImagesByName(t *testing.T) {
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -327,7 +329,7 @@ func TestGetContainersJSON(t *testing.T) {
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -363,7 +365,7 @@ func TestGetContainersExport(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -401,7 +403,7 @@ func TestSaveImageAndThenLoad(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusOK {
@ -415,7 +417,7 @@ func TestSaveImageAndThenLoad(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusOK {
@ -428,7 +430,7 @@ func TestSaveImageAndThenLoad(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusNotFound {
@ -441,7 +443,7 @@ func TestSaveImageAndThenLoad(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusOK {
@ -454,7 +456,7 @@ func TestSaveImageAndThenLoad(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusOK {
@ -481,7 +483,7 @@ func TestGetContainersChanges(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -548,7 +550,7 @@ func TestGetContainersTop(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -596,7 +598,7 @@ func TestGetContainersByName(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -631,7 +633,7 @@ func TestPostCommit(t *testing.T) {
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -667,7 +669,7 @@ func TestPostContainersCreate(t *testing.T) {
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -716,7 +718,7 @@ func TestPostContainersKill(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -755,7 +757,7 @@ func TestPostContainersRestart(t *testing.T) {
t.Fatal(err)
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -797,7 +799,7 @@ func TestPostContainersStart(t *testing.T) {
req.Header.Set("Content-Type", "application/json")
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -814,7 +816,7 @@ func TestPostContainersStart(t *testing.T) {
}
r = httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
// Starting an already started container should return an error
@ -852,7 +854,7 @@ func TestRunErrorBindMountRootSource(t *testing.T) {
req.Header.Set("Content-Type", "application/json")
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusInternalServerError {
@ -889,7 +891,7 @@ func TestPostContainersStop(t *testing.T) {
t.Fatal(err)
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -921,7 +923,7 @@ func TestPostContainersWait(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -979,7 +981,7 @@ func TestPostContainersAttach(t *testing.T) {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r.ResponseRecorder, t)
@ -1057,7 +1059,7 @@ func TestPostContainersAttachStderr(t *testing.T) {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r.ResponseRecorder, t)
@ -1114,7 +1116,7 @@ func TestDeleteContainers(t *testing.T) {
t.Fatal(err)
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -1133,7 +1135,7 @@ func TestOptionsRoute(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -1152,7 +1154,7 @@ func TestGetEnabledCors(t *testing.T) {
if err != nil {
t.Fatal(err)
}
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -1199,7 +1201,7 @@ func TestDeleteImages(t *testing.T) {
}
r := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusConflict {
@ -1212,7 +1214,7 @@ func TestDeleteImages(t *testing.T) {
}
r2 := httptest.NewRecorder()
if err := api.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r2, req2); err != nil {
t.Fatal(err)
}
assertHttpNotError(r2, t)
@ -1264,7 +1266,7 @@ func TestPostContainersCopy(t *testing.T) {
t.Fatal(err)
}
req.Header.Add("Content-Type", "application/json")
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
assertHttpNotError(r, t)
@ -1312,7 +1314,7 @@ func TestPostContainersCopyWhenContainerNotFound(t *testing.T) {
t.Fatal(err)
}
req.Header.Add("Content-Type", "application/json")
if err := api.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
if err := server.ServeRequest(eng, api.APIVERSION, r, req); err != nil {
t.Fatal(err)
}
if r.Code != http.StatusNotFound {

View file

@ -3,7 +3,7 @@ package docker
import (
"bufio"
"fmt"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/api/client"
"github.com/dotcloud/docker/engine"
"github.com/dotcloud/docker/image"
"github.com/dotcloud/docker/pkg/term"
@ -121,7 +121,7 @@ func assertPipe(input, output string, r io.Reader, w io.Writer, count int) error
func TestRunHostname(t *testing.T) {
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -166,7 +166,7 @@ func TestRunHostname(t *testing.T) {
func TestRunWorkdir(t *testing.T) {
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -211,7 +211,7 @@ func TestRunWorkdir(t *testing.T) {
func TestRunWorkdirExists(t *testing.T) {
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -255,7 +255,7 @@ func TestRunWorkdirExists(t *testing.T) {
// TestRunWorkdirExistsAndIsFile checks that if 'docker run -w' with existing file can be detected
func TestRunWorkdirExistsAndIsFile(t *testing.T) {
cli := api.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -275,7 +275,7 @@ func TestRunExit(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c1 := make(chan struct{})
@ -328,7 +328,7 @@ func TestRunDisconnect(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c1 := make(chan struct{})
@ -374,7 +374,7 @@ func TestRunDisconnectTty(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c1 := make(chan struct{})
@ -426,7 +426,7 @@ func TestRunAttachStdin(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@ -490,7 +490,7 @@ func TestRunDetach(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@ -537,7 +537,7 @@ func TestAttachDetach(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
ch := make(chan struct{})
@ -570,7 +570,7 @@ func TestAttachDetach(t *testing.T) {
stdin, stdinPipe = io.Pipe()
stdout, stdoutPipe = io.Pipe()
cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
ch = make(chan struct{})
go func() {
@ -618,7 +618,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
// Discard the CmdRun output
@ -636,7 +636,7 @@ func TestAttachDetachTruncatedID(t *testing.T) {
stdin, stdinPipe = io.Pipe()
stdout, stdoutPipe = io.Pipe()
cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
ch := make(chan struct{})
go func() {
@ -683,7 +683,7 @@ func TestAttachDisconnect(t *testing.T) {
stdin, stdinPipe := io.Pipe()
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
go func() {
@ -752,7 +752,7 @@ func TestAttachDisconnect(t *testing.T) {
func TestRunAutoRemove(t *testing.T) {
t.Skip("Fixme. Skipping test for now, race condition")
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -788,7 +788,7 @@ func TestRunAutoRemove(t *testing.T) {
func TestCmdLogs(t *testing.T) {
t.Skip("Test not impemented")
cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
if err := cli.CmdRun(unitTestImageID, "sh", "-c", "ls -l"); err != nil {
@ -806,7 +806,7 @@ func TestCmdLogs(t *testing.T) {
// Expected behaviour: error out when attempting to bind mount non-existing source paths
func TestRunErrorBindNonExistingSource(t *testing.T) {
cli := api.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, nil, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -826,7 +826,7 @@ func TestRunErrorBindNonExistingSource(t *testing.T) {
func TestImagesViz(t *testing.T) {
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
image := buildTestImages(t, globalEngine)
@ -876,7 +876,7 @@ func TestImagesViz(t *testing.T) {
func TestImagesTree(t *testing.T) {
stdout, stdoutPipe := io.Pipe()
cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
image := buildTestImages(t, globalEngine)
@ -959,7 +959,7 @@ func TestRunCidFileCheckIDLength(t *testing.T) {
}
tmpCidFile := path.Join(tmpDir, "cid")
cli := api.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -1008,7 +1008,7 @@ func TestRunCidFileCleanupIfEmpty(t *testing.T) {
}
tmpCidFile := path.Join(tmpDir, "cid")
cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
c := make(chan struct{})
@ -1038,7 +1038,7 @@ func TestContainerOrphaning(t *testing.T) {
defer os.RemoveAll(tmpDir)
// setup a CLI and server
cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
defer cleanup(globalEngine, t)
srv := mkServerFromEngine(globalEngine, t)
@ -1098,8 +1098,8 @@ func TestCmdKill(t *testing.T) {
var (
stdin, stdinPipe = io.Pipe()
stdout, stdoutPipe = io.Pipe()
cli = api.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli2 = api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli = client.NewDockerCli(stdin, stdoutPipe, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
cli2 = client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto, testDaemonAddr, nil)
)
defer cleanup(globalEngine, t)

View file

@ -3,7 +3,7 @@ package docker
import (
"crypto/tls"
"crypto/x509"
"github.com/dotcloud/docker/api"
"github.com/dotcloud/docker/api/client"
"io/ioutil"
"testing"
"time"
@ -35,7 +35,7 @@ func getTlsConfig(certFile, keyFile string, t *testing.T) *tls.Config {
// TestHttpsInfo connects via two-way authenticated HTTPS to the info endpoint
func TestHttpsInfo(t *testing.T) {
cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
testDaemonHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
@ -48,7 +48,7 @@ func TestHttpsInfo(t *testing.T) {
// TestHttpsInfoRogueCert connects via two-way authenticated HTTPS to the info endpoint
// by using a rogue client certificate and checks that it fails with the expected error.
func TestHttpsInfoRogueCert(t *testing.T) {
cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
testDaemonHttpsAddr, getTlsConfig("client-rogue-cert.pem", "client-rogue-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {
@ -65,7 +65,7 @@ func TestHttpsInfoRogueCert(t *testing.T) {
// TestHttpsInfoRogueServerCert connects via two-way authenticated HTTPS to the info endpoint
// which provides a rogue server certificate and checks that it fails with the expected error
func TestHttpsInfoRogueServerCert(t *testing.T) {
cli := api.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
cli := client.NewDockerCli(nil, ioutil.Discard, ioutil.Discard, testDaemonProto,
testDaemonRogueHttpsAddr, getTlsConfig("client-cert.pem", "client-key.pem", t))
setTimeout(t, "Reading command output time out", 10*time.Second, func() {