Browse Source

Merge pull request #5755 from vieux/move_inspect_daemon

move inspect from server to daemon
Michael Crosby 11 years ago
parent
commit
83e9dc7200

+ 5 - 7
api/server/server.go

@@ -338,7 +338,7 @@ func getContainersLogs(eng *engine.Engine, version version.Version, w http.Respo
 	}
 	}
 
 
 	var (
 	var (
-		job    = eng.Job("inspect", vars["name"], "container")
+		job    = eng.Job("container_inspect", vars["name"])
 		c, err = job.Stdout.AddEnv()
 		c, err = job.Stdout.AddEnv()
 	)
 	)
 	if err != nil {
 	if err != nil {
@@ -755,7 +755,7 @@ func postContainersAttach(eng *engine.Engine, version version.Version, w http.Re
 	}
 	}
 
 
 	var (
 	var (
-		job    = eng.Job("inspect", vars["name"], "container")
+		job    = eng.Job("container_inspect", vars["name"])
 		c, err = job.Stdout.AddEnv()
 		c, err = job.Stdout.AddEnv()
 	)
 	)
 	if err != nil {
 	if err != nil {
@@ -819,7 +819,7 @@ func wsContainersAttach(eng *engine.Engine, version version.Version, w http.Resp
 		return fmt.Errorf("Missing parameter")
 		return fmt.Errorf("Missing parameter")
 	}
 	}
 
 
-	if err := eng.Job("inspect", vars["name"], "container").Run(); err != nil {
+	if err := eng.Job("container_inspect", vars["name"]).Run(); err != nil {
 		return err
 		return err
 	}
 	}
 
 
@@ -847,9 +847,8 @@ func getContainersByName(eng *engine.Engine, version version.Version, w http.Res
 	if vars == nil {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 		return fmt.Errorf("Missing parameter")
 	}
 	}
-	var job = eng.Job("inspect", vars["name"], "container")
+	var job = eng.Job("container_inspect", vars["name"])
 	streamJSON(job, w, false)
 	streamJSON(job, w, false)
-	job.SetenvBool("conflict", true) //conflict=true to detect conflict between containers and images in the job
 	return job.Run()
 	return job.Run()
 }
 }
 
 
@@ -857,9 +856,8 @@ func getImagesByName(eng *engine.Engine, version version.Version, w http.Respons
 	if vars == nil {
 	if vars == nil {
 		return fmt.Errorf("Missing parameter")
 		return fmt.Errorf("Missing parameter")
 	}
 	}
-	var job = eng.Job("inspect", vars["name"], "image")
+	var job = eng.Job("image_inspect", vars["name"])
 	streamJSON(job, w, false)
 	streamJSON(job, w, false)
-	job.SetenvBool("conflict", true) //conflict=true to detect conflict between containers and images in the job
 	return job.Run()
 	return job.Run()
 }
 }
 
 

+ 5 - 0
daemon/daemon.go

@@ -64,6 +64,11 @@ type Daemon struct {
 	execDriver     execdriver.Driver
 	execDriver     execdriver.Driver
 }
 }
 
 
+// Install installs daemon capabilities to eng.
+func (daemon *Daemon) Install(eng *engine.Engine) error {
+	return eng.Register("container_inspect", daemon.ContainerInspect)
+}
+
 // Mountpoints should be private to the container
 // Mountpoints should be private to the container
 func remountPrivate(mountPoint string) error {
 func remountPrivate(mountPoint string) error {
 	mounted, err := mount.Mounted(mountPoint)
 	mounted, err := mount.Mounted(mountPoint)

+ 27 - 0
daemon/inspect.go

@@ -0,0 +1,27 @@
+package daemon
+
+import (
+	"encoding/json"
+
+	"github.com/dotcloud/docker/engine"
+	"github.com/dotcloud/docker/runconfig"
+)
+
+func (daemon *Daemon) ContainerInspect(job *engine.Job) engine.Status {
+	if len(job.Args) != 1 {
+		return job.Errorf("usage: %s NAME", job.Name)
+	}
+	name := job.Args[0]
+	if container := daemon.Get(name); container != nil {
+		b, err := json.Marshal(&struct {
+			*Container
+			HostConfig *runconfig.HostConfig
+		}{container, container.HostConfig()})
+		if err != nil {
+			return job.Error(err)
+		}
+		job.Stdout.Write(b)
+		return engine.StatusOK
+	}
+	return job.Errorf("No such container: %s", name)
+}

+ 48 - 5
graph/service.go

@@ -1,7 +1,10 @@
 package graph
 package graph
 
 
 import (
 import (
+	"encoding/json"
 	"fmt"
 	"fmt"
+	"io"
+
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/engine"
 	"github.com/dotcloud/docker/image"
 	"github.com/dotcloud/docker/image"
 	"github.com/dotcloud/docker/utils"
 	"github.com/dotcloud/docker/utils"
@@ -11,6 +14,8 @@ func (s *TagStore) Install(eng *engine.Engine) error {
 	eng.Register("image_set", s.CmdSet)
 	eng.Register("image_set", s.CmdSet)
 	eng.Register("image_tag", s.CmdTag)
 	eng.Register("image_tag", s.CmdTag)
 	eng.Register("image_get", s.CmdGet)
 	eng.Register("image_get", s.CmdGet)
+	eng.Register("image_inspect", s.CmdLookup)
+	eng.Register("image_tarlayer", s.CmdTarLayer)
 	return nil
 	return nil
 }
 }
 
 
@@ -107,11 +112,6 @@ func (s *TagStore) CmdGet(job *engine.Job) engine.Status {
 		// but we didn't, so now we're doing it here.
 		// but we didn't, so now we're doing it here.
 		//
 		//
 		// Fields that we're probably better off not including:
 		// Fields that we're probably better off not including:
-		//	- ID (the caller already knows it, and we stay more flexible on
-		//		naming down the road)
-		//	- Parent. That field is really an implementation detail of
-		//		layer storage ("layer is a diff against this other layer).
-		//		It doesn't belong at the same level as author/description/etc.
 		//	- Config/ContainerConfig. Those structs have the same sprawl problem,
 		//	- Config/ContainerConfig. Those structs have the same sprawl problem,
 		//		so we shouldn't include them wholesale either.
 		//		so we shouldn't include them wholesale either.
 		//	- Comment: initially created to fulfill the "every image is a git commit"
 		//	- Comment: initially created to fulfill the "every image is a git commit"
@@ -122,7 +122,50 @@ func (s *TagStore) CmdGet(job *engine.Job) engine.Status {
 		res.Set("os", img.OS)
 		res.Set("os", img.OS)
 		res.Set("architecture", img.Architecture)
 		res.Set("architecture", img.Architecture)
 		res.Set("docker_version", img.DockerVersion)
 		res.Set("docker_version", img.DockerVersion)
+		res.Set("ID", img.ID)
+		res.Set("Parent", img.Parent)
 	}
 	}
 	res.WriteTo(job.Stdout)
 	res.WriteTo(job.Stdout)
 	return engine.StatusOK
 	return engine.StatusOK
 }
 }
+
+// CmdLookup return an image encoded in JSON
+func (s *TagStore) CmdLookup(job *engine.Job) engine.Status {
+	if len(job.Args) != 1 {
+		return job.Errorf("usage: %s NAME", job.Name)
+	}
+	name := job.Args[0]
+	if image, err := s.LookupImage(name); err == nil && image != nil {
+		b, err := json.Marshal(image)
+		if err != nil {
+			return job.Error(err)
+		}
+		job.Stdout.Write(b)
+		return engine.StatusOK
+	}
+	return job.Errorf("No such image: %s", name)
+}
+
+// CmdTarLayer return the tarLayer of the image
+func (s *TagStore) CmdTarLayer(job *engine.Job) engine.Status {
+	if len(job.Args) != 1 {
+		return job.Errorf("usage: %s NAME", job.Name)
+	}
+	name := job.Args[0]
+	if image, err := s.LookupImage(name); err == nil && image != nil {
+		fs, err := image.TarLayer()
+		if err != nil {
+			return job.Error(err)
+		}
+		defer fs.Close()
+
+		if written, err := io.Copy(job.Stdout, fs); err != nil {
+			return job.Error(err)
+		} else {
+			utils.Debugf("rendered layer for %s of [%d] size", image.ID, written)
+		}
+
+		return engine.StatusOK
+	}
+	return job.Errorf("No such image: %s", name)
+}

+ 1 - 2
integration/api_test.go

@@ -536,7 +536,6 @@ func TestGetContainersByName(t *testing.T) {
 func TestPostCommit(t *testing.T) {
 func TestPostCommit(t *testing.T) {
 	eng := NewTestEngine(t)
 	eng := NewTestEngine(t)
 	defer mkDaemonFromEngine(eng, t).Nuke()
 	defer mkDaemonFromEngine(eng, t).Nuke()
-	srv := mkServerFromEngine(eng, t)
 
 
 	// Create a container and remove a file
 	// Create a container and remove a file
 	containerID := createTestContainer(eng,
 	containerID := createTestContainer(eng,
@@ -567,7 +566,7 @@ func TestPostCommit(t *testing.T) {
 	if err := env.Decode(r.Body); err != nil {
 	if err := env.Decode(r.Body); err != nil {
 		t.Fatal(err)
 		t.Fatal(err)
 	}
 	}
-	if _, err := srv.ImageInspect(env.Get("Id")); err != nil {
+	if err := eng.Job("image_inspect", env.Get("Id")).Run(); err != nil {
 		t.Fatalf("The image has not been committed")
 		t.Fatalf("The image has not been committed")
 	}
 	}
 }
 }

+ 18 - 7
integration/buildfile_test.go

@@ -1,19 +1,22 @@
 package docker
 package docker
 
 
 import (
 import (
+	"bytes"
+	"encoding/json"
 	"fmt"
 	"fmt"
-	"github.com/dotcloud/docker/archive"
-	"github.com/dotcloud/docker/engine"
-	"github.com/dotcloud/docker/image"
-	"github.com/dotcloud/docker/nat"
-	"github.com/dotcloud/docker/server"
-	"github.com/dotcloud/docker/utils"
 	"io/ioutil"
 	"io/ioutil"
 	"net"
 	"net"
 	"net/http"
 	"net/http"
 	"net/http/httptest"
 	"net/http/httptest"
 	"strings"
 	"strings"
 	"testing"
 	"testing"
+
+	"github.com/dotcloud/docker/archive"
+	"github.com/dotcloud/docker/engine"
+	"github.com/dotcloud/docker/image"
+	"github.com/dotcloud/docker/nat"
+	"github.com/dotcloud/docker/server"
+	"github.com/dotcloud/docker/utils"
 )
 )
 
 
 // A testContextTemplate describes a build context and how to test it
 // A testContextTemplate describes a build context and how to test it
@@ -400,7 +403,15 @@ func buildImage(context testContextTemplate, t *testing.T, eng *engine.Engine, u
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	return srv.ImageInspect(id)
+	job := eng.Job("image_inspect", id)
+	buffer := bytes.NewBuffer(nil)
+	image := &image.Image{}
+	job.Stdout.Add(buffer)
+	if err := job.Run(); err != nil {
+		return nil, err
+	}
+	err = json.NewDecoder(buffer).Decode(image)
+	return image, err
 }
 }
 
 
 func TestVolume(t *testing.T) {
 func TestVolume(t *testing.T) {

+ 4 - 3
integration/commands_test.go

@@ -1052,11 +1052,12 @@ func TestContainerOrphaning(t *testing.T) {
 		if err := cli.CmdBuild("-t", image, tmpDir); err != nil {
 		if err := cli.CmdBuild("-t", image, tmpDir); err != nil {
 			t.Fatal(err)
 			t.Fatal(err)
 		}
 		}
-		img, err := srv.ImageInspect(image)
-		if err != nil {
+		job := globalEngine.Job("image_get", image)
+		info, _ := job.Stdout.AddEnv()
+		if err := job.Run(); err != nil {
 			t.Fatal(err)
 			t.Fatal(err)
 		}
 		}
-		return img.ID
+		return info.Get("ID")
 	}
 	}
 
 
 	// build an image
 	// build an image

+ 2 - 2
integration/server_test.go

@@ -81,13 +81,13 @@ func TestMergeConfigOnCommit(t *testing.T) {
 	container2, _, _ := mkContainer(runtime, []string{engine.Tail(outputBuffer, 1)}, t)
 	container2, _, _ := mkContainer(runtime, []string{engine.Tail(outputBuffer, 1)}, t)
 	defer runtime.Destroy(container2)
 	defer runtime.Destroy(container2)
 
 
-	job = eng.Job("inspect", container1.Name, "container")
+	job = eng.Job("container_inspect", container1.Name)
 	baseContainer, _ := job.Stdout.AddEnv()
 	baseContainer, _ := job.Stdout.AddEnv()
 	if err := job.Run(); err != nil {
 	if err := job.Run(); err != nil {
 		t.Error(err)
 		t.Error(err)
 	}
 	}
 
 
-	job = eng.Job("inspect", container2.Name, "container")
+	job = eng.Job("container_inspect", container2.Name)
 	commitContainer, _ := job.Stdout.AddEnv()
 	commitContainer, _ := job.Stdout.AddEnv()
 	if err := job.Run(); err != nil {
 	if err := job.Run(); err != nil {
 		t.Error(err)
 		t.Error(err)

+ 27 - 99
server/server.go

@@ -132,7 +132,6 @@ func InitServer(job *engine.Job) engine.Status {
 		"pull":             srv.ImagePull,
 		"pull":             srv.ImagePull,
 		"import":           srv.ImageImport,
 		"import":           srv.ImageImport,
 		"image_delete":     srv.ImageDelete,
 		"image_delete":     srv.ImageDelete,
-		"inspect":          srv.JobInspect,
 		"events":           srv.Events,
 		"events":           srv.Events,
 		"push":             srv.ImagePush,
 		"push":             srv.ImagePush,
 		"containers":       srv.Containers,
 		"containers":       srv.Containers,
@@ -146,6 +145,11 @@ func InitServer(job *engine.Job) engine.Status {
 	if err := srv.daemon.Repositories().Install(job.Eng); err != nil {
 	if err := srv.daemon.Repositories().Install(job.Eng); err != nil {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}
+	// Install daemon-related commands from the daemon subsystem.
+	// See `daemon/`
+	if err := srv.daemon.Install(job.Eng); err != nil {
+		return job.Error(err)
+	}
 	return engine.StatusOK
 	return engine.StatusOK
 }
 }
 
 
@@ -327,12 +331,7 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status {
 	}
 	}
 	if rootRepo != nil {
 	if rootRepo != nil {
 		for _, id := range rootRepo {
 		for _, id := range rootRepo {
-			image, err := srv.ImageInspect(id)
-			if err != nil {
-				return job.Error(err)
-			}
-
-			if err := srv.exportImage(image, tempdir); err != nil {
+			if err := srv.exportImage(job.Eng, id, tempdir); err != nil {
 				return job.Error(err)
 				return job.Error(err)
 			}
 			}
 		}
 		}
@@ -346,11 +345,7 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status {
 			return job.Error(err)
 			return job.Error(err)
 		}
 		}
 	} else {
 	} else {
-		image, err := srv.ImageInspect(name)
-		if err != nil {
-			return job.Error(err)
-		}
-		if err := srv.exportImage(image, tempdir); err != nil {
+		if err := srv.exportImage(job.Eng, name, tempdir); err != nil {
 			return job.Error(err)
 			return job.Error(err)
 		}
 		}
 	}
 	}
@@ -364,13 +359,14 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status {
 	if _, err := io.Copy(job.Stdout, fs); err != nil {
 	if _, err := io.Copy(job.Stdout, fs); err != nil {
 		return job.Error(err)
 		return job.Error(err)
 	}
 	}
+	utils.Debugf("End Serializing %s", name)
 	return engine.StatusOK
 	return engine.StatusOK
 }
 }
 
 
-func (srv *Server) exportImage(img *image.Image, tempdir string) error {
-	for i := img; i != nil; {
+func (srv *Server) exportImage(eng *engine.Engine, name, tempdir string) error {
+	for n := name; n != ""; {
 		// temporary directory
 		// temporary directory
-		tmpImageDir := path.Join(tempdir, i.ID)
+		tmpImageDir := path.Join(tempdir, n)
 		if err := os.Mkdir(tmpImageDir, os.FileMode(0755)); err != nil {
 		if err := os.Mkdir(tmpImageDir, os.FileMode(0755)); err != nil {
 			if os.IsExist(err) {
 			if os.IsExist(err) {
 				return nil
 				return nil
@@ -386,44 +382,34 @@ func (srv *Server) exportImage(img *image.Image, tempdir string) error {
 		}
 		}
 
 
 		// serialize json
 		// serialize json
-		b, err := json.Marshal(i)
+		json, err := os.Create(path.Join(tmpImageDir, "json"))
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		if err := ioutil.WriteFile(path.Join(tmpImageDir, "json"), b, os.FileMode(0644)); err != nil {
+		job := eng.Job("image_inspect", n)
+		job.Stdout.Add(json)
+		if err := job.Run(); err != nil {
 			return err
 			return err
 		}
 		}
 
 
 		// serialize filesystem
 		// serialize filesystem
-		fs, err := i.TarLayer()
-		if err != nil {
-			return err
-		}
-		defer fs.Close()
-
 		fsTar, err := os.Create(path.Join(tmpImageDir, "layer.tar"))
 		fsTar, err := os.Create(path.Join(tmpImageDir, "layer.tar"))
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		if written, err := io.Copy(fsTar, fs); err != nil {
-			return err
-		} else {
-			utils.Debugf("rendered layer for %s of [%d] size", i.ID, written)
-		}
-
-		if err = fsTar.Close(); err != nil {
+		job = eng.Job("image_tarlayer", n)
+		job.Stdout.Add(fsTar)
+		if err := job.Run(); err != nil {
 			return err
 			return err
 		}
 		}
 
 
 		// find parent
 		// find parent
-		if i.Parent != "" {
-			i, err = srv.ImageInspect(i.Parent)
-			if err != nil {
-				return err
-			}
-		} else {
-			i = nil
+		job = eng.Job("image_get", n)
+		info, _ := job.Stdout.AddEnv()
+		if err := job.Run(); err != nil {
+			return err
 		}
 		}
+		n = info.Get("Parent")
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -548,7 +534,7 @@ func (srv *Server) ImageLoad(job *engine.Job) engine.Status {
 
 
 	for _, d := range dirs {
 	for _, d := range dirs {
 		if d.IsDir() {
 		if d.IsDir() {
-			if err := srv.recursiveLoad(d.Name(), tmpImageDir); err != nil {
+			if err := srv.recursiveLoad(job.Eng, d.Name(), tmpImageDir); err != nil {
 				return job.Error(err)
 				return job.Error(err)
 			}
 			}
 		}
 		}
@@ -575,8 +561,8 @@ func (srv *Server) ImageLoad(job *engine.Job) engine.Status {
 	return engine.StatusOK
 	return engine.StatusOK
 }
 }
 
 
-func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
-	if _, err := srv.ImageInspect(address); err != nil {
+func (srv *Server) recursiveLoad(eng *engine.Engine, address, tmpImageDir string) error {
+	if err := eng.Job("image_get", address).Run(); err != nil {
 		utils.Debugf("Loading %s", address)
 		utils.Debugf("Loading %s", address)
 
 
 		imageJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", address, "json"))
 		imageJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", address, "json"))
@@ -597,7 +583,7 @@ func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
 		}
 		}
 		if img.Parent != "" {
 		if img.Parent != "" {
 			if !srv.daemon.Graph().Exists(img.Parent) {
 			if !srv.daemon.Graph().Exists(img.Parent) {
-				if err := srv.recursiveLoad(img.Parent, tmpImageDir); err != nil {
+				if err := srv.recursiveLoad(eng, img.Parent, tmpImageDir); err != nil {
 					return err
 					return err
 				}
 				}
 			}
 			}
@@ -2341,64 +2327,6 @@ func (srv *Server) ContainerAttach(job *engine.Job) engine.Status {
 	return engine.StatusOK
 	return engine.StatusOK
 }
 }
 
 
-func (srv *Server) ContainerInspect(name string) (*daemon.Container, error) {
-	if container := srv.daemon.Get(name); container != nil {
-		return container, nil
-	}
-	return nil, fmt.Errorf("No such container: %s", name)
-}
-
-func (srv *Server) ImageInspect(name string) (*image.Image, error) {
-	if image, err := srv.daemon.Repositories().LookupImage(name); err == nil && image != nil {
-		return image, nil
-	}
-	return nil, fmt.Errorf("No such image: %s", name)
-}
-
-func (srv *Server) JobInspect(job *engine.Job) engine.Status {
-	// TODO: deprecate KIND/conflict
-	if n := len(job.Args); n != 2 {
-		return job.Errorf("Usage: %s CONTAINER|IMAGE KIND", job.Name)
-	}
-	var (
-		name                    = job.Args[0]
-		kind                    = job.Args[1]
-		object                  interface{}
-		conflict                = job.GetenvBool("conflict") //should the job detect conflict between containers and images
-		image, errImage         = srv.ImageInspect(name)
-		container, errContainer = srv.ContainerInspect(name)
-	)
-
-	if conflict && image != nil && container != nil {
-		return job.Errorf("Conflict between containers and images")
-	}
-
-	switch kind {
-	case "image":
-		if errImage != nil {
-			return job.Error(errImage)
-		}
-		object = image
-	case "container":
-		if errContainer != nil {
-			return job.Error(errContainer)
-		}
-		object = &struct {
-			*daemon.Container
-			HostConfig *runconfig.HostConfig
-		}{container, container.HostConfig()}
-	default:
-		return job.Errorf("Unknown kind: %s", kind)
-	}
-
-	b, err := json.Marshal(object)
-	if err != nil {
-		return job.Error(err)
-	}
-	job.Stdout.Write(b)
-	return engine.StatusOK
-}
-
 func (srv *Server) ContainerCopy(job *engine.Job) engine.Status {
 func (srv *Server) ContainerCopy(job *engine.Job) engine.Status {
 	if len(job.Args) != 2 {
 	if len(job.Args) != 2 {
 		return job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name)
 		return job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name)