Browse code

improve rmi

Victor Vieux authored on 2013/05/15 22:11:39
Showing 4 changed files
... ...
@@ -1189,8 +1189,51 @@ func TestDeleteContainers(t *testing.T) {
1189 1189
 }
1190 1190
 
1191 1191
 func TestDeleteImages(t *testing.T) {
1192
-	//FIXME: Implement this test
1193
-	t.Log("Test not implemented")
1192
+	runtime, err := newTestRuntime()
1193
+	if err != nil {
1194
+		t.Fatal(err)
1195
+	}
1196
+	defer nuke(runtime)
1197
+
1198
+	srv := &Server{runtime: runtime}
1199
+
1200
+	if err := srv.runtime.repositories.Set("test", "test", unitTestImageName, true); err != nil {
1201
+		t.Fatal(err)
1202
+	}
1203
+
1204
+	images, err := srv.Images(false, "")
1205
+	if err != nil {
1206
+		t.Fatal(err)
1207
+	}
1208
+
1209
+	if len(images) != 2 {
1210
+		t.Errorf("Excepted 2 images, %d found", len(images))
1211
+	}
1212
+
1213
+	r := httptest.NewRecorder()
1214
+	if err := deleteImages(srv, r, nil, map[string]string{"name": "test:test"}); err != nil {
1215
+		t.Fatal(err)
1216
+	}
1217
+	if r.Code != http.StatusNoContent {
1218
+		t.Fatalf("%d NO CONTENT expected, received %d\n", http.StatusNoContent, r.Code)
1219
+	}
1220
+
1221
+	images, err = srv.Images(false, "")
1222
+	if err != nil {
1223
+		t.Fatal(err)
1224
+	}
1225
+
1226
+	if len(images) != 1 {
1227
+		t.Errorf("Excepted 1 image, %d found", len(images))
1228
+	}
1229
+
1230
+	/*	if c := runtime.Get(container.Id); c != nil {
1231
+			t.Fatalf("The container as not been deleted")
1232
+		}
1233
+
1234
+		if _, err := os.Stat(path.Join(container.rwPath(), "test")); err == nil {
1235
+			t.Fatalf("The test file has not been deleted")
1236
+		} */
1194 1237
 }
1195 1238
 
1196 1239
 // Mocked types for tests
... ...
@@ -439,9 +439,45 @@ func (srv *Server) ImageDelete(name string) error {
439 439
 	if err != nil {
440 440
 		return fmt.Errorf("No such image: %s", name)
441 441
 	} else {
442
+		tag := ""
443
+		if strings.Contains(name, ":") {
444
+			nameParts := strings.Split(name, ":")
445
+			name = nameParts[0]
446
+			tag = nameParts[1]
447
+		}
448
+		// if the images is referenced several times
449
+		Debugf("Image %s referenced %d times", img.Id, len(srv.runtime.repositories.ById()[img.Id]))
450
+		if len(srv.runtime.repositories.ById()[img.Id]) > 1 {
451
+			// if it's repo:tag, try to delete the tag (docker rmi base:latest)
452
+			if tag != "" {
453
+				if err := srv.runtime.repositories.Delete(name, tag, img.Id); err != nil {
454
+					return err
455
+				}
456
+				return nil
457
+			} else {
458
+				// check if the image is referenced in another repo (base and user/base are the same, docker rmi user/base)
459
+				var other bool
460
+				for _, repoTag := range srv.runtime.repositories.ById()[img.Id] {
461
+					if !strings.Contains(repoTag, name+":") {
462
+						other = true
463
+						break
464
+					}
465
+				}
466
+				// if found in another repo, delete the repo, other delete the whole image (docker rmi base)
467
+				if other {
468
+					if err := srv.runtime.repositories.Delete(name, "", img.Id); err != nil {
469
+						return err
470
+					}
471
+					return nil
472
+				}
473
+			}
474
+		}
442 475
 		if err := srv.runtime.graph.Delete(img.Id); err != nil {
443 476
 			return fmt.Errorf("Error deleting image %s: %s", name, err.Error())
444 477
 		}
478
+		if err := srv.runtime.repositories.Delete(name, tag, img.Id); err != nil {
479
+			return err
480
+		}
445 481
 	}
446 482
 	return nil
447 483
 }
... ...
@@ -4,6 +4,58 @@ import (
4 4
 	"testing"
5 5
 )
6 6
 
7
+func TestContainerTagImageDelete(t *testing.T) {
8
+	runtime, err := newTestRuntime()
9
+	if err != nil {
10
+		t.Fatal(err)
11
+	}
12
+	defer nuke(runtime)
13
+
14
+	srv := &Server{runtime: runtime}
15
+
16
+	if err := srv.runtime.repositories.Set("utest", "tag1", unitTestImageName, false); err != nil {
17
+		t.Fatal(err)
18
+	}
19
+	if err := srv.runtime.repositories.Set("utest/docker", "tag2", unitTestImageName, false); err != nil {
20
+		t.Fatal(err)
21
+	}
22
+
23
+	images, err := srv.Images(false, "")
24
+	if err != nil {
25
+		t.Fatal(err)
26
+	}
27
+
28
+	if len(images) != 3 {
29
+		t.Errorf("Excepted 3 images, %d found", len(images))
30
+	}
31
+
32
+	if err := srv.ImageDelete("utest/docker:tag2"); err != nil {
33
+		t.Fatal(err)
34
+	}
35
+
36
+	images, err = srv.Images(false, "")
37
+	if err != nil {
38
+		t.Fatal(err)
39
+	}
40
+
41
+	if len(images) != 2 {
42
+		t.Errorf("Excepted 2 images, %d found", len(images))
43
+	}
44
+
45
+	if err := srv.ImageDelete("utest:tag1"); err != nil {
46
+		t.Fatal(err)
47
+	}
48
+
49
+	images, err = srv.Images(false, "")
50
+	if err != nil {
51
+		t.Fatal(err)
52
+	}
53
+
54
+	if len(images) != 1 {
55
+		t.Errorf("Excepted 1 image, %d found", len(images))
56
+	}
57
+}
58
+
7 59
 func TestCreateRm(t *testing.T) {
8 60
 	runtime, err := newTestRuntime()
9 61
 	if err != nil {
... ...
@@ -109,6 +109,29 @@ func (store *TagStore) ImageName(id string) string {
109 109
 	return TruncateId(id)
110 110
 }
111 111
 
112
+func (store *TagStore) Delete(repoName, tag, imageName string) error {
113
+	if err := store.Reload(); err != nil {
114
+		return err
115
+	}
116
+	if r, exists := store.Repositories[repoName]; exists {
117
+		if tag != "" {
118
+			if _, exists2 := r[tag]; exists2 {
119
+				delete(r, tag)
120
+				if len(r) == 0 {
121
+					delete(store.Repositories, repoName)
122
+				}
123
+			} else {
124
+				return fmt.Errorf("No such tag: %s:%s", repoName, tag)
125
+			}
126
+		} else {
127
+			delete(store.Repositories, repoName)
128
+		}
129
+	} else {
130
+		fmt.Errorf("No such repository: %s", repoName)
131
+	}
132
+	return store.Save()
133
+}
134
+
112 135
 func (store *TagStore) Set(repoName, tag, imageName string, force bool) error {
113 136
 	img, err := store.LookupImage(imageName)
114 137
 	if err != nil {