Browse code

move inspect from server to daemon

Docker-DCO-1.1-Signed-off-by: Victor Vieux <vieux@docker.com> (github: vieux)

Victor Vieux authored on 2014/05/21 04:36:15
Showing 9 changed files
... ...
@@ -338,7 +338,7 @@ func getContainersLogs(eng *engine.Engine, version version.Version, w http.Respo
338 338
 	}
339 339
 
340 340
 	var (
341
-		job    = eng.Job("inspect", vars["name"], "container")
341
+		job    = eng.Job("container_inspect", vars["name"])
342 342
 		c, err = job.Stdout.AddEnv()
343 343
 	)
344 344
 	if err != nil {
... ...
@@ -755,7 +755,7 @@ func postContainersAttach(eng *engine.Engine, version version.Version, w http.Re
755 755
 	}
756 756
 
757 757
 	var (
758
-		job    = eng.Job("inspect", vars["name"], "container")
758
+		job    = eng.Job("container_inspect", vars["name"])
759 759
 		c, err = job.Stdout.AddEnv()
760 760
 	)
761 761
 	if err != nil {
... ...
@@ -819,7 +819,7 @@ func wsContainersAttach(eng *engine.Engine, version version.Version, w http.Resp
819 819
 		return fmt.Errorf("Missing parameter")
820 820
 	}
821 821
 
822
-	if err := eng.Job("inspect", vars["name"], "container").Run(); err != nil {
822
+	if err := eng.Job("container_inspect", vars["name"]).Run(); err != nil {
823 823
 		return err
824 824
 	}
825 825
 
... ...
@@ -847,9 +847,8 @@ func getContainersByName(eng *engine.Engine, version version.Version, w http.Res
847 847
 	if vars == nil {
848 848
 		return fmt.Errorf("Missing parameter")
849 849
 	}
850
-	var job = eng.Job("inspect", vars["name"], "container")
850
+	var job = eng.Job("container_inspect", vars["name"])
851 851
 	streamJSON(job, w, false)
852
-	job.SetenvBool("conflict", true) //conflict=true to detect conflict between containers and images in the job
853 852
 	return job.Run()
854 853
 }
855 854
 
... ...
@@ -857,9 +856,8 @@ func getImagesByName(eng *engine.Engine, version version.Version, w http.Respons
857 857
 	if vars == nil {
858 858
 		return fmt.Errorf("Missing parameter")
859 859
 	}
860
-	var job = eng.Job("inspect", vars["name"], "image")
860
+	var job = eng.Job("image_inspect", vars["name"])
861 861
 	streamJSON(job, w, false)
862
-	job.SetenvBool("conflict", true) //conflict=true to detect conflict between containers and images in the job
863 862
 	return job.Run()
864 863
 }
865 864
 
... ...
@@ -64,6 +64,11 @@ type Daemon struct {
64 64
 	execDriver     execdriver.Driver
65 65
 }
66 66
 
67
+// Install installs daemon capabilities to eng.
68
+func (daemon *Daemon) Install(eng *engine.Engine) error {
69
+	return eng.Register("container_inspect", daemon.ContainerInspect)
70
+}
71
+
67 72
 // Mountpoints should be private to the container
68 73
 func remountPrivate(mountPoint string) error {
69 74
 	mounted, err := mount.Mounted(mountPoint)
70 75
new file mode 100644
... ...
@@ -0,0 +1,27 @@
0
+package daemon
1
+
2
+import (
3
+	"encoding/json"
4
+
5
+	"github.com/dotcloud/docker/engine"
6
+	"github.com/dotcloud/docker/runconfig"
7
+)
8
+
9
+func (daemon *Daemon) ContainerInspect(job *engine.Job) engine.Status {
10
+	if len(job.Args) != 1 {
11
+		return job.Errorf("usage: %s NAME", job.Name)
12
+	}
13
+	name := job.Args[0]
14
+	if container := daemon.Get(name); container != nil {
15
+		b, err := json.Marshal(&struct {
16
+			*Container
17
+			HostConfig *runconfig.HostConfig
18
+		}{container, container.HostConfig()})
19
+		if err != nil {
20
+			return job.Error(err)
21
+		}
22
+		job.Stdout.Write(b)
23
+		return engine.StatusOK
24
+	}
25
+	return job.Errorf("No such container: %s", name)
26
+}
... ...
@@ -1,7 +1,10 @@
1 1
 package graph
2 2
 
3 3
 import (
4
+	"encoding/json"
4 5
 	"fmt"
6
+	"io"
7
+
5 8
 	"github.com/dotcloud/docker/engine"
6 9
 	"github.com/dotcloud/docker/image"
7 10
 	"github.com/dotcloud/docker/utils"
... ...
@@ -11,6 +14,8 @@ func (s *TagStore) Install(eng *engine.Engine) error {
11 11
 	eng.Register("image_set", s.CmdSet)
12 12
 	eng.Register("image_tag", s.CmdTag)
13 13
 	eng.Register("image_get", s.CmdGet)
14
+	eng.Register("image_inspect", s.CmdLookup)
15
+	eng.Register("image_tarlayer", s.CmdTarLayer)
14 16
 	return nil
15 17
 }
16 18
 
... ...
@@ -107,11 +112,6 @@ func (s *TagStore) CmdGet(job *engine.Job) engine.Status {
107 107
 		// but we didn't, so now we're doing it here.
108 108
 		//
109 109
 		// Fields that we're probably better off not including:
110
-		//	- ID (the caller already knows it, and we stay more flexible on
111
-		//		naming down the road)
112
-		//	- Parent. That field is really an implementation detail of
113
-		//		layer storage ("layer is a diff against this other layer).
114
-		//		It doesn't belong at the same level as author/description/etc.
115 110
 		//	- Config/ContainerConfig. Those structs have the same sprawl problem,
116 111
 		//		so we shouldn't include them wholesale either.
117 112
 		//	- 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 {
122 122
 		res.Set("os", img.OS)
123 123
 		res.Set("architecture", img.Architecture)
124 124
 		res.Set("docker_version", img.DockerVersion)
125
+		res.Set("ID", img.ID)
126
+		res.Set("Parent", img.Parent)
125 127
 	}
126 128
 	res.WriteTo(job.Stdout)
127 129
 	return engine.StatusOK
128 130
 }
131
+
132
+// CmdLookup return an image encoded in JSON
133
+func (s *TagStore) CmdLookup(job *engine.Job) engine.Status {
134
+	if len(job.Args) != 1 {
135
+		return job.Errorf("usage: %s NAME", job.Name)
136
+	}
137
+	name := job.Args[0]
138
+	if image, err := s.LookupImage(name); err == nil && image != nil {
139
+		b, err := json.Marshal(image)
140
+		if err != nil {
141
+			return job.Error(err)
142
+		}
143
+		job.Stdout.Write(b)
144
+		return engine.StatusOK
145
+	}
146
+	return job.Errorf("No such image: %s", name)
147
+}
148
+
149
+// CmdTarLayer return the tarLayer of the image
150
+func (s *TagStore) CmdTarLayer(job *engine.Job) engine.Status {
151
+	if len(job.Args) != 1 {
152
+		return job.Errorf("usage: %s NAME", job.Name)
153
+	}
154
+	name := job.Args[0]
155
+	if image, err := s.LookupImage(name); err == nil && image != nil {
156
+		fs, err := image.TarLayer()
157
+		if err != nil {
158
+			return job.Error(err)
159
+		}
160
+		defer fs.Close()
161
+
162
+		if written, err := io.Copy(job.Stdout, fs); err != nil {
163
+			return job.Error(err)
164
+		} else {
165
+			utils.Debugf("rendered layer for %s of [%d] size", image.ID, written)
166
+		}
167
+
168
+		return engine.StatusOK
169
+	}
170
+	return job.Errorf("No such image: %s", name)
171
+}
... ...
@@ -536,7 +536,6 @@ func TestGetContainersByName(t *testing.T) {
536 536
 func TestPostCommit(t *testing.T) {
537 537
 	eng := NewTestEngine(t)
538 538
 	defer mkDaemonFromEngine(eng, t).Nuke()
539
-	srv := mkServerFromEngine(eng, t)
540 539
 
541 540
 	// Create a container and remove a file
542 541
 	containerID := createTestContainer(eng,
... ...
@@ -567,7 +566,7 @@ func TestPostCommit(t *testing.T) {
567 567
 	if err := env.Decode(r.Body); err != nil {
568 568
 		t.Fatal(err)
569 569
 	}
570
-	if _, err := srv.ImageInspect(env.Get("Id")); err != nil {
570
+	if err := eng.Job("image_inspect", env.Get("Id")).Run(); err != nil {
571 571
 		t.Fatalf("The image has not been committed")
572 572
 	}
573 573
 }
... ...
@@ -1,19 +1,22 @@
1 1
 package docker
2 2
 
3 3
 import (
4
+	"bytes"
5
+	"encoding/json"
4 6
 	"fmt"
5
-	"github.com/dotcloud/docker/archive"
6
-	"github.com/dotcloud/docker/engine"
7
-	"github.com/dotcloud/docker/image"
8
-	"github.com/dotcloud/docker/nat"
9
-	"github.com/dotcloud/docker/server"
10
-	"github.com/dotcloud/docker/utils"
11 7
 	"io/ioutil"
12 8
 	"net"
13 9
 	"net/http"
14 10
 	"net/http/httptest"
15 11
 	"strings"
16 12
 	"testing"
13
+
14
+	"github.com/dotcloud/docker/archive"
15
+	"github.com/dotcloud/docker/engine"
16
+	"github.com/dotcloud/docker/image"
17
+	"github.com/dotcloud/docker/nat"
18
+	"github.com/dotcloud/docker/server"
19
+	"github.com/dotcloud/docker/utils"
17 20
 )
18 21
 
19 22
 // 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
400 400
 		return nil, err
401 401
 	}
402 402
 
403
-	return srv.ImageInspect(id)
403
+	job := eng.Job("image_inspect", id)
404
+	buffer := bytes.NewBuffer(nil)
405
+	image := &image.Image{}
406
+	job.Stdout.Add(buffer)
407
+	if err := job.Run(); err != nil {
408
+		return nil, err
409
+	}
410
+	err = json.NewDecoder(buffer).Decode(image)
411
+	return image, err
404 412
 }
405 413
 
406 414
 func TestVolume(t *testing.T) {
... ...
@@ -1052,11 +1052,12 @@ func TestContainerOrphaning(t *testing.T) {
1052 1052
 		if err := cli.CmdBuild("-t", image, tmpDir); err != nil {
1053 1053
 			t.Fatal(err)
1054 1054
 		}
1055
-		img, err := srv.ImageInspect(image)
1056
-		if err != nil {
1055
+		job := globalEngine.Job("image_get", image)
1056
+		info, _ := job.Stdout.AddEnv()
1057
+		if err := job.Run(); err != nil {
1057 1058
 			t.Fatal(err)
1058 1059
 		}
1059
-		return img.ID
1060
+		return info.Get("ID")
1060 1061
 	}
1061 1062
 
1062 1063
 	// build an image
... ...
@@ -81,13 +81,13 @@ func TestMergeConfigOnCommit(t *testing.T) {
81 81
 	container2, _, _ := mkContainer(runtime, []string{engine.Tail(outputBuffer, 1)}, t)
82 82
 	defer runtime.Destroy(container2)
83 83
 
84
-	job = eng.Job("inspect", container1.Name, "container")
84
+	job = eng.Job("container_inspect", container1.Name)
85 85
 	baseContainer, _ := job.Stdout.AddEnv()
86 86
 	if err := job.Run(); err != nil {
87 87
 		t.Error(err)
88 88
 	}
89 89
 
90
-	job = eng.Job("inspect", container2.Name, "container")
90
+	job = eng.Job("container_inspect", container2.Name)
91 91
 	commitContainer, _ := job.Stdout.AddEnv()
92 92
 	if err := job.Run(); err != nil {
93 93
 		t.Error(err)
... ...
@@ -132,7 +132,6 @@ func InitServer(job *engine.Job) engine.Status {
132 132
 		"pull":             srv.ImagePull,
133 133
 		"import":           srv.ImageImport,
134 134
 		"image_delete":     srv.ImageDelete,
135
-		"inspect":          srv.JobInspect,
136 135
 		"events":           srv.Events,
137 136
 		"push":             srv.ImagePush,
138 137
 		"containers":       srv.Containers,
... ...
@@ -146,6 +145,11 @@ func InitServer(job *engine.Job) engine.Status {
146 146
 	if err := srv.daemon.Repositories().Install(job.Eng); err != nil {
147 147
 		return job.Error(err)
148 148
 	}
149
+	// Install daemon-related commands from the daemon subsystem.
150
+	// See `daemon/`
151
+	if err := srv.daemon.Install(job.Eng); err != nil {
152
+		return job.Error(err)
153
+	}
149 154
 	return engine.StatusOK
150 155
 }
151 156
 
... ...
@@ -327,12 +331,7 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status {
327 327
 	}
328 328
 	if rootRepo != nil {
329 329
 		for _, id := range rootRepo {
330
-			image, err := srv.ImageInspect(id)
331
-			if err != nil {
332
-				return job.Error(err)
333
-			}
334
-
335
-			if err := srv.exportImage(image, tempdir); err != nil {
330
+			if err := srv.exportImage(job.Eng, id, tempdir); err != nil {
336 331
 				return job.Error(err)
337 332
 			}
338 333
 		}
... ...
@@ -346,11 +345,7 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status {
346 346
 			return job.Error(err)
347 347
 		}
348 348
 	} else {
349
-		image, err := srv.ImageInspect(name)
350
-		if err != nil {
351
-			return job.Error(err)
352
-		}
353
-		if err := srv.exportImage(image, tempdir); err != nil {
349
+		if err := srv.exportImage(job.Eng, name, tempdir); err != nil {
354 350
 			return job.Error(err)
355 351
 		}
356 352
 	}
... ...
@@ -364,13 +359,14 @@ func (srv *Server) ImageExport(job *engine.Job) engine.Status {
364 364
 	if _, err := io.Copy(job.Stdout, fs); err != nil {
365 365
 		return job.Error(err)
366 366
 	}
367
+	utils.Debugf("End Serializing %s", name)
367 368
 	return engine.StatusOK
368 369
 }
369 370
 
370
-func (srv *Server) exportImage(img *image.Image, tempdir string) error {
371
-	for i := img; i != nil; {
371
+func (srv *Server) exportImage(eng *engine.Engine, name, tempdir string) error {
372
+	for n := name; n != ""; {
372 373
 		// temporary directory
373
-		tmpImageDir := path.Join(tempdir, i.ID)
374
+		tmpImageDir := path.Join(tempdir, n)
374 375
 		if err := os.Mkdir(tmpImageDir, os.FileMode(0755)); err != nil {
375 376
 			if os.IsExist(err) {
376 377
 				return nil
... ...
@@ -386,44 +382,34 @@ func (srv *Server) exportImage(img *image.Image, tempdir string) error {
386 386
 		}
387 387
 
388 388
 		// serialize json
389
-		b, err := json.Marshal(i)
389
+		json, err := os.Create(path.Join(tmpImageDir, "json"))
390 390
 		if err != nil {
391 391
 			return err
392 392
 		}
393
-		if err := ioutil.WriteFile(path.Join(tmpImageDir, "json"), b, os.FileMode(0644)); err != nil {
393
+		job := eng.Job("image_inspect", n)
394
+		job.Stdout.Add(json)
395
+		if err := job.Run(); err != nil {
394 396
 			return err
395 397
 		}
396 398
 
397 399
 		// serialize filesystem
398
-		fs, err := i.TarLayer()
399
-		if err != nil {
400
-			return err
401
-		}
402
-		defer fs.Close()
403
-
404 400
 		fsTar, err := os.Create(path.Join(tmpImageDir, "layer.tar"))
405 401
 		if err != nil {
406 402
 			return err
407 403
 		}
408
-		if written, err := io.Copy(fsTar, fs); err != nil {
409
-			return err
410
-		} else {
411
-			utils.Debugf("rendered layer for %s of [%d] size", i.ID, written)
412
-		}
413
-
414
-		if err = fsTar.Close(); err != nil {
404
+		job = eng.Job("image_tarlayer", n)
405
+		job.Stdout.Add(fsTar)
406
+		if err := job.Run(); err != nil {
415 407
 			return err
416 408
 		}
417 409
 
418 410
 		// find parent
419
-		if i.Parent != "" {
420
-			i, err = srv.ImageInspect(i.Parent)
421
-			if err != nil {
422
-				return err
423
-			}
424
-		} else {
425
-			i = nil
411
+		job = eng.Job("image_get", n)
412
+		info, _ := job.Stdout.AddEnv()
413
+		if err := job.Run(); err != nil {
414
+			return err
426 415
 		}
416
+		n = info.Get("Parent")
427 417
 	}
428 418
 	return nil
429 419
 }
... ...
@@ -548,7 +534,7 @@ func (srv *Server) ImageLoad(job *engine.Job) engine.Status {
548 548
 
549 549
 	for _, d := range dirs {
550 550
 		if d.IsDir() {
551
-			if err := srv.recursiveLoad(d.Name(), tmpImageDir); err != nil {
551
+			if err := srv.recursiveLoad(job.Eng, d.Name(), tmpImageDir); err != nil {
552 552
 				return job.Error(err)
553 553
 			}
554 554
 		}
... ...
@@ -575,8 +561,8 @@ func (srv *Server) ImageLoad(job *engine.Job) engine.Status {
575 575
 	return engine.StatusOK
576 576
 }
577 577
 
578
-func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
579
-	if _, err := srv.ImageInspect(address); err != nil {
578
+func (srv *Server) recursiveLoad(eng *engine.Engine, address, tmpImageDir string) error {
579
+	if err := eng.Job("image_get", address).Run(); err != nil {
580 580
 		utils.Debugf("Loading %s", address)
581 581
 
582 582
 		imageJson, err := ioutil.ReadFile(path.Join(tmpImageDir, "repo", address, "json"))
... ...
@@ -597,7 +583,7 @@ func (srv *Server) recursiveLoad(address, tmpImageDir string) error {
597 597
 		}
598 598
 		if img.Parent != "" {
599 599
 			if !srv.daemon.Graph().Exists(img.Parent) {
600
-				if err := srv.recursiveLoad(img.Parent, tmpImageDir); err != nil {
600
+				if err := srv.recursiveLoad(eng, img.Parent, tmpImageDir); err != nil {
601 601
 					return err
602 602
 				}
603 603
 			}
... ...
@@ -2337,64 +2323,6 @@ func (srv *Server) ContainerAttach(job *engine.Job) engine.Status {
2337 2337
 	return engine.StatusOK
2338 2338
 }
2339 2339
 
2340
-func (srv *Server) ContainerInspect(name string) (*daemon.Container, error) {
2341
-	if container := srv.daemon.Get(name); container != nil {
2342
-		return container, nil
2343
-	}
2344
-	return nil, fmt.Errorf("No such container: %s", name)
2345
-}
2346
-
2347
-func (srv *Server) ImageInspect(name string) (*image.Image, error) {
2348
-	if image, err := srv.daemon.Repositories().LookupImage(name); err == nil && image != nil {
2349
-		return image, nil
2350
-	}
2351
-	return nil, fmt.Errorf("No such image: %s", name)
2352
-}
2353
-
2354
-func (srv *Server) JobInspect(job *engine.Job) engine.Status {
2355
-	// TODO: deprecate KIND/conflict
2356
-	if n := len(job.Args); n != 2 {
2357
-		return job.Errorf("Usage: %s CONTAINER|IMAGE KIND", job.Name)
2358
-	}
2359
-	var (
2360
-		name                    = job.Args[0]
2361
-		kind                    = job.Args[1]
2362
-		object                  interface{}
2363
-		conflict                = job.GetenvBool("conflict") //should the job detect conflict between containers and images
2364
-		image, errImage         = srv.ImageInspect(name)
2365
-		container, errContainer = srv.ContainerInspect(name)
2366
-	)
2367
-
2368
-	if conflict && image != nil && container != nil {
2369
-		return job.Errorf("Conflict between containers and images")
2370
-	}
2371
-
2372
-	switch kind {
2373
-	case "image":
2374
-		if errImage != nil {
2375
-			return job.Error(errImage)
2376
-		}
2377
-		object = image
2378
-	case "container":
2379
-		if errContainer != nil {
2380
-			return job.Error(errContainer)
2381
-		}
2382
-		object = &struct {
2383
-			*daemon.Container
2384
-			HostConfig *runconfig.HostConfig
2385
-		}{container, container.HostConfig()}
2386
-	default:
2387
-		return job.Errorf("Unknown kind: %s", kind)
2388
-	}
2389
-
2390
-	b, err := json.Marshal(object)
2391
-	if err != nil {
2392
-		return job.Error(err)
2393
-	}
2394
-	job.Stdout.Write(b)
2395
-	return engine.StatusOK
2396
-}
2397
-
2398 2340
 func (srv *Server) ContainerCopy(job *engine.Job) engine.Status {
2399 2341
 	if len(job.Args) != 2 {
2400 2342
 		return job.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name)