diff --git a/api.go b/api.go index 63698c81bb..820d36983d 100644 --- a/api.go +++ b/api.go @@ -327,17 +327,7 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht sf := utils.NewStreamFormatter(version > 1.0) if image != "" { //pull registry := r.Form.Get("registry") - authConfig := &auth.AuthConfig{} - if version > 1.1 { - json.NewDecoder(r.Body).Decode(authConfig) - } else { - localAuthConfig, err := auth.LoadConfig(srv.runtime.root) - if err != nil && err != auth.ErrConfigFileMissing { - return err - } - authConfig = localAuthConfig - } - if err := srv.ImagePull(image, tag, registry, w, sf, authConfig); err != nil { + if err := srv.ImagePull(image, tag, registry, w, sf, &auth.AuthConfig{}); err != nil { if sf.Used() { w.Write(sf.FormatError(err)) return nil diff --git a/api_params.go b/api_params.go index 1a24ab2875..e18238b735 100644 --- a/api_params.go +++ b/api_params.go @@ -3,7 +3,7 @@ package docker type ApiHistory struct { Id string Created int64 - CreatedBy string + CreatedBy string `json:",omitempty"` } type ApiImages struct { @@ -14,13 +14,13 @@ type ApiImages struct { } type ApiInfo struct { - Containers int - Version string - Images int Debug bool - GoVersion string - NFd int `json:",omitempty"` - NGoroutines int `json:",omitempty"` + Containers int + Images int + NFd int `json:",omitempty"` + NGoroutines int `json:",omitempty"` + MemoryLimit bool `json:",omitempty"` + SwapLimit bool `json:",omitempty"` } type ApiContainers struct { @@ -43,7 +43,7 @@ type ApiId struct { type ApiRun struct { Id string - Warnings []string + Warnings []string `json:",omitempty"` } type ApiPort struct { @@ -51,10 +51,9 @@ type ApiPort struct { } type ApiVersion struct { - Version string - GitCommit string - MemoryLimit bool - SwapLimit bool + Version string + GitCommit string `json:",omitempty"` + GoVersion string `json:",omitempty"` } type ApiWait struct { diff --git a/api_test.go b/api_test.go index b0f1444367..57c71ac324 100644 --- a/api_test.go +++ b/api_test.go @@ -99,8 +99,8 @@ func TestGetInfo(t *testing.T) { if err != nil { t.Fatal(err) } - if infos.Version != VERSION { - t.Errorf("Excepted version %s, %s found", VERSION, infos.Version) + if infos.Images != 1 { + t.Errorf("Excepted images: %d, %d found", 1, infos.Images) } } diff --git a/changes.go b/changes.go index 4c79918887..e50b88758a 100644 --- a/changes.go +++ b/changes.go @@ -65,7 +65,7 @@ func Changes(layers []string, rw string) ([]Change, error) { file := filepath.Base(path) // If there is a whiteout, then the file was removed if strings.HasPrefix(file, ".wh.") { - originalFile := strings.TrimLeft(file, ".wh.") + originalFile := strings.TrimPrefix(file, ".wh.") change.Path = filepath.Join(filepath.Dir(path), originalFile) change.Kind = ChangeDelete } else { diff --git a/commands.go b/commands.go index 2538cd06c9..fbe72b6e93 100644 --- a/commands.go +++ b/commands.go @@ -383,15 +383,14 @@ func (cli *DockerCli) CmdVersion(args ...string) error { utils.Debugf("Error unmarshal: body: %s, err: %s\n", body, err) return err } - fmt.Println("Version:", out.Version) - fmt.Println("Git Commit:", out.GitCommit) - if !out.MemoryLimit { - fmt.Println("WARNING: No memory limit support") + fmt.Println("Client version:", VERSION) + fmt.Println("Server version:", out.Version) + if out.GitCommit != "" { + fmt.Println("Git commit:", out.GitCommit) } - if !out.SwapLimit { - fmt.Println("WARNING: No swap limit support") + if out.GoVersion != "" { + fmt.Println("Go version:", out.GoVersion) } - return nil } @@ -412,14 +411,23 @@ func (cli *DockerCli) CmdInfo(args ...string) error { } var out ApiInfo - err = json.Unmarshal(body, &out) - if err != nil { + if err := json.Unmarshal(body, &out); err != nil { return err } - fmt.Printf("containers: %d\nversion: %s\nimages: %d\nGo version: %s\n", out.Containers, out.Version, out.Images, out.GoVersion) - if out.Debug { - fmt.Println("debug mode enabled") - fmt.Printf("fds: %d\ngoroutines: %d\n", out.NFd, out.NGoroutines) + + fmt.Printf("Containers: %d\n", out.Containers) + fmt.Printf("Images: %d\n", out.Images) + if out.Debug || os.Getenv("DEBUG") != "" { + fmt.Printf("Debug mode (server): %v\n", out.Debug) + fmt.Printf("Debug mode (client): %v\n", os.Getenv("DEBUG") != "") + fmt.Printf("Fds: %d\n", out.NFd) + fmt.Printf("Goroutines: %d\n", out.NGoroutines) + } + if !out.MemoryLimit { + fmt.Println("WARNING: No memory limit support") + } + if !out.SwapLimit { + fmt.Println("WARNING: No swap limit support") } return nil } @@ -693,9 +701,14 @@ func (cli *DockerCli) CmdPush(args ...string) error { return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in / (ex: %s/%s)", cli.authConfig.Username, name) } + buf, err := json.Marshal(cli.authConfig) + if err != nil { + return err + } + v := url.Values{} v.Set("registry", *registry) - if err := cli.stream("POST", "/images/"+name+"/push?"+v.Encode(), nil, os.Stdout); err != nil { + if err := cli.stream("POST", "/images/"+name+"/push?"+v.Encode(), bytes.NewBuffer(buf), os.Stdout); err != nil { return err } return nil @@ -721,12 +734,6 @@ func (cli *DockerCli) CmdPull(args ...string) error { remote = remoteParts[0] } - if strings.Contains(remote, "/") { - if err := cli.checkIfLogged(true, "pull"); err != nil { - return err - } - } - v := url.Values{} v.Set("fromImage", remote) v.Set("tag", *tag) @@ -1383,7 +1390,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.Fi return err }) - if in != nil && setRawTerminal && term.IsTerminal(int(in.Fd())) && os.Getenv("NORAW") == "" { + if in != nil && setRawTerminal && term.IsTerminal(in.Fd()) && os.Getenv("NORAW") == "" { if oldState, err := term.SetRawTerminal(); err != nil { return err } else { @@ -1402,7 +1409,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.Fi return err } - if !term.IsTerminal(int(os.Stdin.Fd())) { + if !term.IsTerminal(os.Stdin.Fd()) { if err := <-sendStdin; err != nil { return err } diff --git a/container_test.go b/container_test.go index 3ed1763a3e..117f0f3eb3 100644 --- a/container_test.go +++ b/container_test.go @@ -217,6 +217,37 @@ func TestDiff(t *testing.T) { t.Fatalf("/etc/passwd should not be present in the diff after commit.") } } + + // Create a new containere + container3, err := builder.Create( + &Config{ + Image: GetTestImage(runtime).Id, + Cmd: []string{"rm", "/bin/httpd"}, + }, + ) + if err != nil { + t.Fatal(err) + } + defer runtime.Destroy(container3) + + if err := container3.Run(); err != nil { + t.Fatal(err) + } + + // Check the changelog + c, err = container3.Changes() + if err != nil { + t.Fatal(err) + } + success = false + for _, elem := range c { + if elem.Path == "/bin/httpd" && elem.Kind == 2 { + success = true + } + } + if !success { + t.Fatalf("/bin/httpd should be present in the diff after commit.") + } } func TestCommitAutoRun(t *testing.T) { diff --git a/docs/sources/api/docker_remote_api.rst b/docs/sources/api/docker_remote_api.rst index f6e2795857..a42d623391 100644 --- a/docs/sources/api/docker_remote_api.rst +++ b/docs/sources/api/docker_remote_api.rst @@ -14,7 +14,7 @@ Docker Remote API - The Remote API is replacing rcli - Default port in the docker deamon is 4243 - The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr -- Since API version 1.2, the auth configuration is now handled client side, so the client has to send the authConfig as POST in /images/create and /images//pull +- Since API version 1.2, the auth configuration is now handled client side, so the client has to send the authConfig as POST in /images/create 2. Version ========== @@ -551,19 +551,12 @@ Create an image Create an image, either by pull it from the registry or by importing it - **Example request v1.0**: + **Example request**: .. sourcecode:: http POST /images/create?fromImage=base HTTP/1.1 - **Example request v1.2**: - - .. sourcecode:: http - - POST /images/create?fromImage=base HTTP/1.1 - {{ authConfig }} - **Example response v1.1**: .. sourcecode:: http @@ -972,10 +965,12 @@ Display system-wide information { "Containers":11, - "Version":"0.2.2", "Images":16, - "GoVersion":"go1.0.3", - "Debug":false + "Debug":false, + "NFd": 11, + "NGoroutines":21, + "MemoryLimit":true, + "SwapLimit":false } :statuscode 200: no error @@ -1001,12 +996,11 @@ Show the docker version information HTTP/1.1 200 OK Content-Type: application/json - + { "Version":"0.2.2", "GitCommit":"5a2a5cc+CHANGES", - "MemoryLimit":true, - "SwapLimit":false + "GoVersion":"go1.0.3" } :statuscode 200: no error diff --git a/server.go b/server.go index c90f64bb15..2a4b103654 100644 --- a/server.go +++ b/server.go @@ -17,7 +17,11 @@ import ( ) func (srv *Server) DockerVersion() ApiVersion { - return ApiVersion{VERSION, GIT_COMMIT, srv.runtime.capabilities.MemoryLimit, srv.runtime.capabilities.SwapLimit} + return ApiVersion{ + Version: VERSION, + GitCommit: GIT_COMMIT, + GoVersion: runtime.Version(), + } } func (srv *Server) ContainerKill(name string) error { @@ -187,7 +191,7 @@ func (srv *Server) Images(all bool, filter string) ([]ApiImages, error) { return outs, nil } -func (srv *Server) DockerInfo() ApiInfo { +func (srv *Server) DockerInfo() *ApiInfo { images, _ := srv.runtime.graph.All() var imgcount int if images == nil { @@ -195,17 +199,15 @@ func (srv *Server) DockerInfo() ApiInfo { } else { imgcount = len(images) } - var out ApiInfo - out.Containers = len(srv.runtime.List()) - out.Version = VERSION - out.Images = imgcount - out.GoVersion = runtime.Version() - if os.Getenv("DEBUG") != "" { - out.Debug = true - out.NFd = utils.GetTotalUsedFds() - out.NGoroutines = runtime.NumGoroutine() + return &ApiInfo{ + Containers: len(srv.runtime.List()), + Images: imgcount, + MemoryLimit: srv.runtime.capabilities.MemoryLimit, + SwapLimit: srv.runtime.capabilities.SwapLimit, + Debug: os.Getenv("DEBUG") != "", + NFd: utils.GetTotalUsedFds(), + NGoroutines: runtime.NumGoroutine(), } - return out } func (srv *Server) ImageHistory(name string) ([]ApiHistory, error) { @@ -395,7 +397,6 @@ func (srv *Server) pullRepository(r *registry.Registry, out io.Writer, remote, a } func (srv *Server) ImagePull(name, tag, endpoint string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig) error { - utils.Debugf("ImagePull from <%s>", authConfig.Username) r := registry.NewRegistry(srv.runtime.root, authConfig) out = utils.NewWriteFlusher(out) if endpoint != "" { @@ -578,7 +579,6 @@ func (srv *Server) pushImage(r *registry.Registry, out io.Writer, remote, imgId, } func (srv *Server) ImagePush(name, endpoint string, out io.Writer, sf *utils.StreamFormatter, authConfig *auth.AuthConfig) error { - utils.Debugf("ImagePush from <%s>", authConfig.Username) out = utils.NewWriteFlusher(out) img, err := srv.runtime.graph.Get(name) r := registry.NewRegistry(srv.runtime.root, authConfig) diff --git a/term/term.go b/term/term.go index 290bf174ad..0cc91ea1b6 100644 --- a/term/term.go +++ b/term/term.go @@ -7,104 +7,6 @@ import ( "unsafe" ) -type Termios struct { - Iflag uintptr - Oflag uintptr - Cflag uintptr - Lflag uintptr - Cc [20]byte - Ispeed uintptr - Ospeed uintptr -} - -const ( - // Input flags - inpck = 0x010 - istrip = 0x020 - icrnl = 0x100 - ixon = 0x200 - - // Output flags - opost = 0x1 - - // Control flags - cs8 = 0x300 - - // Local flags - icanon = 0x100 - iexten = 0x400 -) - -const ( - HUPCL = 0x4000 - ICANON = 0x100 - ICRNL = 0x100 - IEXTEN = 0x400 - BRKINT = 0x2 - CFLUSH = 0xf - CLOCAL = 0x8000 - CREAD = 0x800 - CS5 = 0x0 - CS6 = 0x100 - CS7 = 0x200 - CS8 = 0x300 - CSIZE = 0x300 - CSTART = 0x11 - CSTATUS = 0x14 - CSTOP = 0x13 - CSTOPB = 0x400 - CSUSP = 0x1a - IGNBRK = 0x1 - IGNCR = 0x80 - IGNPAR = 0x4 - IMAXBEL = 0x2000 - INLCR = 0x40 - INPCK = 0x10 - ISIG = 0x80 - ISTRIP = 0x20 - IUTF8 = 0x4000 - IXANY = 0x800 - IXOFF = 0x400 - IXON = 0x200 - NOFLSH = 0x80000000 - OCRNL = 0x10 - OFDEL = 0x20000 - OFILL = 0x80 - ONLCR = 0x2 - ONLRET = 0x40 - ONOCR = 0x20 - ONOEOT = 0x8 - OPOST = 0x1 - RENB = 0x1000 - PARMRK = 0x8 - PARODD = 0x2000 - - TOSTOP = 0x400000 - VDISCARD = 0xf - VDSUSP = 0xb - VEOF = 0x0 - VEOL = 0x1 - VEOL2 = 0x2 - VERASE = 0x3 - VINTR = 0x8 - VKILL = 0x5 - VLNEXT = 0xe - VMIN = 0x10 - VQUIT = 0x9 - VREPRINT = 0x6 - VSTART = 0xc - VSTATUS = 0x12 - VSTOP = 0xd - VSUSP = 0xa - VT0 = 0x0 - VT1 = 0x10000 - VTDLY = 0x10000 - VTIME = 0x11 - ECHO = 0x00000008 - - PENDIN = 0x20000000 -) - type State struct { termios Termios } @@ -128,21 +30,21 @@ func SetWinsize(fd uintptr, ws *Winsize) error { } // IsTerminal returns true if the given file descriptor is a terminal. -func IsTerminal(fd int) bool { +func IsTerminal(fd uintptr) bool { var termios Termios - _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&termios))) + _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&termios))) return err == 0 } // Restore restores the terminal connected to the given file descriptor to a // previous state. -func Restore(fd int, state *State) error { - _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios))) +func Restore(fd uintptr, state *State) error { + _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&state.termios))) return err } func SetRawTerminal() (*State, error) { - oldState, err := MakeRaw(int(os.Stdin.Fd())) + oldState, err := MakeRaw(os.Stdin.Fd()) if err != nil { return nil, err } @@ -150,12 +52,12 @@ func SetRawTerminal() (*State, error) { signal.Notify(c, os.Interrupt) go func() { _ = <-c - Restore(int(os.Stdin.Fd()), oldState) + Restore(os.Stdin.Fd(), oldState) os.Exit(0) }() return oldState, err } func RestoreTerminal(state *State) { - Restore(int(os.Stdin.Fd()), state) + Restore(os.Stdin.Fd(), state) } diff --git a/term/termios_darwin.go b/term/termios_darwin.go index 7df54e7828..ac18aab692 100644 --- a/term/termios_darwin.go +++ b/term/termios_darwin.go @@ -8,23 +8,45 @@ import ( const ( getTermios = syscall.TIOCGETA setTermios = syscall.TIOCSETA + + ECHO = 0x00000008 + ONLCR = 0x2 + ISTRIP = 0x20 + INLCR = 0x40 + ISIG = 0x80 + IGNCR = 0x80 + ICANON = 0x100 + ICRNL = 0x100 + IXOFF = 0x400 + IXON = 0x200 ) +type Termios struct { + Iflag uint64 + Oflag uint64 + Cflag uint64 + Lflag uint64 + Cc [20]byte + Ispeed uint64 + Ospeed uint64 +} + // MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. -func MakeRaw(fd int) (*State, error) { +func MakeRaw(fd uintptr) (*State, error) { var oldState State - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(getTermios), uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { return nil, err } newState := oldState.termios - newState.Iflag &^= ISTRIP | INLCR | IGNCR | IXON | IXOFF + newState.Iflag &^= (ISTRIP | INLCR | IGNCR | IXON | IXOFF) newState.Iflag |= ICRNL newState.Oflag |= ONLCR - newState.Lflag &^= ECHO | ICANON | ISIG - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), uintptr(setTermios), uintptr(unsafe.Pointer(&newState)), 0, 0, 0); err != 0 { + newState.Lflag &^= (ECHO | ICANON | ISIG) + + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(setTermios), uintptr(unsafe.Pointer(&newState))); err != 0 { return nil, err } diff --git a/term/termios_linux.go b/term/termios_linux.go index 92f21edde2..4a717c84a7 100644 --- a/term/termios_linux.go +++ b/term/termios_linux.go @@ -5,54 +5,40 @@ import ( "unsafe" ) -// #include -// #include -/* -void MakeRaw(int fd) { - struct termios t; - - // FIXME: Handle errors? - ioctl(fd, TCGETS, &t); - - t.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON); - t.c_oflag &= ~OPOST; - t.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN | ISIG); - t.c_cflag &= ~(CSIZE | PARENB); - t.c_cflag |= CS8; - - ioctl(fd, TCSETS, &t); -} -*/ -import "C" - const ( getTermios = syscall.TCGETS setTermios = syscall.TCSETS ) +type Termios struct { + Iflag uint32 + Oflag uint32 + Cflag uint32 + Lflag uint32 + Cc [20]byte + Ispeed uint32 + Ospeed uint32 +} + // MakeRaw put the terminal connected to the given file descriptor into raw // mode and returns the previous state of the terminal so that it can be // restored. -func MakeRaw(fd int) (*State, error) { +func MakeRaw(fd uintptr) (*State, error) { var oldState State - if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, uintptr(fd), syscall.TCGETS, uintptr(unsafe.Pointer(&oldState.termios)), 0, 0, 0); err != 0 { + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, getTermios, uintptr(unsafe.Pointer(&oldState.termios))); err != 0 { + return nil, err + } + + newState := oldState.termios + + newState.Iflag &^= (syscall.IGNBRK | syscall.BRKINT | syscall.PARMRK | syscall.ISTRIP | syscall.INLCR | syscall.IGNCR | syscall.ICRNL | syscall.IXON) + newState.Oflag &^= syscall.OPOST + newState.Lflag &^= (syscall.ECHO | syscall.ECHONL | syscall.ICANON | syscall.ISIG | syscall.IEXTEN) + newState.Cflag &^= (syscall.CSIZE | syscall.PARENB) + newState.Cflag |= syscall.CS8 + + if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, fd, setTermios, uintptr(unsafe.Pointer(&newState))); err != 0 { return nil, err } - C.MakeRaw(C.int(fd)) return &oldState, nil - - // FIXME: post on goland issues this: very same as the C function bug non-working - - // newState := oldState.termios - - // newState.Iflag &^= (IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON) - // newState.Oflag &^= OPOST - // newState.Lflag &^= (ECHO | syscall.ECHONL | ICANON | ISIG | IEXTEN) - // newState.Cflag &^= (CSIZE | syscall.PARENB) - // newState.Cflag |= CS8 - - // if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), syscall.TCSETS, uintptr(unsafe.Pointer(&newState))); err != 0 { - // return nil, err - // } - // return &oldState, nil }