Forráskód Böngészése

Added various debugging commands: cat, write, ls, inspect, mount, umount

Solomon Hykes 12 éve
szülő
commit
6df37208be
2 módosított fájl, 169 hozzáadás és 0 törlés
  1. 148 0
      dockerd/dockerd.go
  2. 21 0
      filesystem.go

+ 148 - 0
dockerd/dockerd.go

@@ -16,6 +16,8 @@ import (
 	"os"
 	"time"
 	"net/http"
+	"encoding/json"
+	"bytes"
 )
 
 
@@ -70,6 +72,152 @@ func (srv *Server) CmdStop(stdin io.ReadCloser, stdout io.Writer, args ...string
 	return nil
 }
 
+func (srv *Server) CmdUmount(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
+	cmd := rcli.Subcmd(stdout, "umount", "[OPTIONS] NAME", "umount a container's filesystem (debug only)")
+	if err := cmd.Parse(args); err != nil {
+		cmd.Usage()
+		return nil
+	}
+	if cmd.NArg() < 1 {
+		cmd.Usage()
+		return nil
+	}
+	for _, name := range cmd.Args() {
+		if container, exists := srv.findContainer(name); exists {
+			if err := container.Filesystem.Umount(); err != nil {
+				return err
+			}
+			fmt.Fprintln(stdout, container.Id)
+		} else {
+			return errors.New("No such container: " + name)
+		}
+	}
+	return nil
+}
+
+func (srv *Server) CmdMount(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
+	cmd := rcli.Subcmd(stdout, "umount", "[OPTIONS] NAME", "mount a container's filesystem (debug only)")
+	if err := cmd.Parse(args); err != nil {
+		cmd.Usage()
+		return nil
+	}
+	if cmd.NArg() < 1 {
+		cmd.Usage()
+		return nil
+	}
+	for _, name := range cmd.Args() {
+		if container, exists := srv.findContainer(name); exists {
+			if err := container.Filesystem.Mount(); err != nil {
+				return err
+			}
+			fmt.Fprintln(stdout, container.Id)
+		} else {
+			return errors.New("No such container: " + name)
+		}
+	}
+	return nil
+}
+
+func (srv *Server) CmdCat(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
+	cmd := rcli.Subcmd(stdout, "cat", "[OPTIONS] CONTAINER PATH", "write the contents of a container's file to standard output")
+	if err := cmd.Parse(args); err != nil {
+		cmd.Usage()
+		return nil
+	}
+	if cmd.NArg() < 2 {
+		cmd.Usage()
+		return nil
+	}
+	name, path := cmd.Arg(0), cmd.Arg(1)
+	if container, exists := srv.findContainer(name); exists {
+		if f, err := container.Filesystem.OpenFile(path, os.O_RDONLY, 0); err != nil {
+			return err
+		} else if _, err := io.Copy(stdout, f); err != nil {
+			return err
+		}
+		return nil
+	}
+	return errors.New("No such container: " + name)
+}
+
+func (srv *Server) CmdWrite(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
+	cmd := rcli.Subcmd(stdout, "write", "[OPTIONS] CONTAINER PATH", "write the contents of standard input to a container's file")
+	if err := cmd.Parse(args); err != nil {
+		cmd.Usage()
+		return nil
+	}
+	if cmd.NArg() < 2 {
+		cmd.Usage()
+		return nil
+	}
+	name, path := cmd.Arg(0), cmd.Arg(1)
+	if container, exists := srv.findContainer(name); exists {
+		if f, err := container.Filesystem.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0600); err != nil {
+			return err
+		} else if _, err := io.Copy(f, stdin); err != nil {
+			return err
+		}
+		return nil
+	}
+	return errors.New("No such container: " + name)
+}
+
+
+func (srv *Server) CmdLs(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
+	cmd := rcli.Subcmd(stdout, "ls", "[OPTIONS] CONTAINER PATH", "List the contents of a container's directory")
+	if err := cmd.Parse(args); err != nil {
+		cmd.Usage()
+		return nil
+	}
+	if cmd.NArg() < 2 {
+		cmd.Usage()
+		return nil
+	}
+	name, path := cmd.Arg(0), cmd.Arg(1)
+	if container, exists := srv.findContainer(name); exists {
+		if files, err := container.Filesystem.ReadDir(path); err != nil {
+			return err
+		} else {
+			for _, f := range files {
+				fmt.Fprintln(stdout, f.Name())
+			}
+		}
+		return nil
+	}
+	return errors.New("No such container: " + name)
+}
+
+func (srv *Server) CmdInspect(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
+	cmd := rcli.Subcmd(stdout, "inspect", "[OPTIONS] CONTAINER", "Return low-level information on a container")
+	if err := cmd.Parse(args); err != nil {
+		cmd.Usage()
+		return nil
+	}
+	if cmd.NArg() < 1 {
+		cmd.Usage()
+		return nil
+	}
+	name := cmd.Arg(0)
+	if container, exists := srv.findContainer(name); exists {
+		data, err := json.Marshal(container)
+		if err != nil {
+			return err
+		}
+		indented := new(bytes.Buffer)
+		if err = json.Indent(indented, data, "", "    "); err != nil {
+			return err
+		}
+		if _, err := io.Copy(stdout, indented); err != nil {
+			return err
+		}
+		return nil
+	}
+	return errors.New("No such container: " + name)
+}
+
+
+
+
 func (srv *Server) CmdList(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
 	flags := rcli.Subcmd(stdout, "list", "[OPTIONS] [NAME]", "List containers")
 	limit := flags.Int("l", 0, "Only show the N most recent versions of each name")

+ 21 - 0
filesystem.go

@@ -7,6 +7,8 @@ import (
 	"path/filepath"
 	"strings"
 	"syscall"
+	"io"
+	"io/ioutil"
 )
 
 type Filesystem struct {
@@ -180,16 +182,35 @@ func (fs *Filesystem) Changes() ([]Change, error) {
 	return changes, nil
 }
 
+// Reset removes all changes to the filesystem, reverting it to its initial state.
 func (fs *Filesystem) Reset() error {
 	if err := os.RemoveAll(fs.RWPath); err != nil {
 		return err
 	}
+	// We removed the RW directory itself along with its content: let's re-create an empty one.
 	if err := fs.createMountPoints(); err != nil {
 		return err
 	}
 	return nil
 }
 
+// Open opens the named file for reading.
+func (fs *Filesystem) OpenFile(path string, flag int, perm os.FileMode) (*os.File, error) {
+	if err := fs.EnsureMounted(); err != nil {
+		return nil, err
+	}
+	return os.OpenFile(filepath.Join(fs.RootFS, path), flag, perm)
+}
+
+// ReadDir reads the directory named by dirname, relative to the Filesystem's root,
+// and returns a list of sorted directory entries
+func (fs *Filesystem) ReadDir(dirname string) ([]os.FileInfo, error) {
+	if err := fs.EnsureMounted(); err != nil {
+		return nil, err
+	}
+	return ioutil.ReadDir(filepath.Join(fs.RootFS, dirname))
+}
+
 func newFilesystem(rootfs string, rwpath string, layers []string) *Filesystem {
 	return &Filesystem{
 		RootFS: rootfs,