Signed-off-by: Andy Goldstein <agoldste@redhat.com>
| ... | ... |
@@ -1518,29 +1518,32 @@ func (cli *DockerCli) CmdImages(args ...string) error {
|
| 1518 | 1518 |
outID = common.TruncateID(outID) |
| 1519 | 1519 |
} |
| 1520 | 1520 |
|
| 1521 |
- // Tags referring to this image ID. |
|
| 1522 |
- for _, repotag := range out.GetList("RepoTags") {
|
|
| 1523 |
- repo, tag := parsers.ParseRepositoryTag(repotag) |
|
| 1521 |
+ repoTags := out.GetList("RepoTags")
|
|
| 1522 |
+ repoDigests := out.GetList("RepoDigests")
|
|
| 1524 | 1523 |
|
| 1525 |
- if !*quiet {
|
|
| 1526 |
- if *showDigests {
|
|
| 1527 |
- fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, "<none>", outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
|
|
| 1528 |
- } else {
|
|
| 1529 |
- fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
|
|
| 1530 |
- } |
|
| 1524 |
+ if len(repoTags) == 1 && repoTags[0] == "<none>:<none>" && len(repoDigests) == 1 && repoDigests[0] == "<none>@<none>" {
|
|
| 1525 |
+ // dangling image - clear out either repoTags or repoDigsts so we only show it once below |
|
| 1526 |
+ repoDigests = []string{}
|
|
| 1527 |
+ } |
|
| 1528 |
+ |
|
| 1529 |
+ // combine the tags and digests lists |
|
| 1530 |
+ tagsAndDigests := append(repoTags, repoDigests...) |
|
| 1531 |
+ for _, repoAndRef := range tagsAndDigests {
|
|
| 1532 |
+ repo, ref := parsers.ParseRepositoryTag(repoAndRef) |
|
| 1533 |
+ // default tag and digest to none - if there's a value, it'll be set below |
|
| 1534 |
+ tag := "<none>" |
|
| 1535 |
+ digest := "<none>" |
|
| 1536 |
+ if utils.DigestReference(ref) {
|
|
| 1537 |
+ digest = ref |
|
| 1531 | 1538 |
} else {
|
| 1532 |
- fmt.Fprintln(w, outID) |
|
| 1539 |
+ tag = ref |
|
| 1533 | 1540 |
} |
| 1534 |
- } |
|
| 1535 | 1541 |
|
| 1536 |
- // Digests referring to this image ID. |
|
| 1537 |
- for _, repoDigest := range out.GetList("RepoDigests") {
|
|
| 1538 |
- repo, digest := parsers.ParseRepositoryTag(repoDigest) |
|
| 1539 | 1542 |
if !*quiet {
|
| 1540 | 1543 |
if *showDigests {
|
| 1541 |
- fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, "<none>", digest, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
|
|
| 1544 |
+ fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s ago\t%s\n", repo, tag, digest, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
|
|
| 1542 | 1545 |
} else {
|
| 1543 |
- fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, "<none>", outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
|
|
| 1546 |
+ fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\n", repo, tag, outID, units.HumanDuration(time.Now().UTC().Sub(time.Unix(out.GetInt64("Created"), 0))), units.HumanSize(float64(out.GetInt64("VirtualSize"))))
|
|
| 1544 | 1547 |
} |
| 1545 | 1548 |
} else {
|
| 1546 | 1549 |
fmt.Fprintln(w, outID) |
| ... | ... |
@@ -8,6 +8,8 @@ import ( |
| 8 | 8 |
"strings" |
| 9 | 9 |
"testing" |
| 10 | 10 |
"time" |
| 11 |
+ |
|
| 12 |
+ "github.com/docker/docker/pkg/common" |
|
| 11 | 13 |
) |
| 12 | 14 |
|
| 13 | 15 |
func TestImagesEnsureImageIsListed(t *testing.T) {
|
| ... | ... |
@@ -176,3 +178,44 @@ func TestImagesFilterWhiteSpaceTrimmingAndLowerCasingWorking(t *testing.T) {
|
| 176 | 176 |
|
| 177 | 177 |
logDone("images - white space trimming and lower casing")
|
| 178 | 178 |
} |
| 179 |
+ |
|
| 180 |
+func TestImagesEnsureDanglingImageOnlyListedOnce(t *testing.T) {
|
|
| 181 |
+ defer deleteAllContainers() |
|
| 182 |
+ |
|
| 183 |
+ // create container 1 |
|
| 184 |
+ c := exec.Command(dockerBinary, "run", "-d", "busybox", "true") |
|
| 185 |
+ out, _, err := runCommandWithOutput(c) |
|
| 186 |
+ if err != nil {
|
|
| 187 |
+ t.Fatalf("error running busybox: %s, %v", out, err)
|
|
| 188 |
+ } |
|
| 189 |
+ containerId1 := strings.TrimSpace(out) |
|
| 190 |
+ |
|
| 191 |
+ // tag as foobox |
|
| 192 |
+ c = exec.Command(dockerBinary, "commit", containerId1, "foobox") |
|
| 193 |
+ out, _, err = runCommandWithOutput(c) |
|
| 194 |
+ if err != nil {
|
|
| 195 |
+ t.Fatalf("error tagging foobox: %s", err)
|
|
| 196 |
+ } |
|
| 197 |
+ imageId := common.TruncateID(strings.TrimSpace(out)) |
|
| 198 |
+ defer deleteImages(imageId) |
|
| 199 |
+ |
|
| 200 |
+ // overwrite the tag, making the previous image dangling |
|
| 201 |
+ c = exec.Command(dockerBinary, "tag", "-f", "busybox", "foobox") |
|
| 202 |
+ out, _, err = runCommandWithOutput(c) |
|
| 203 |
+ if err != nil {
|
|
| 204 |
+ t.Fatalf("error tagging foobox: %s", err)
|
|
| 205 |
+ } |
|
| 206 |
+ defer deleteImages("foobox")
|
|
| 207 |
+ |
|
| 208 |
+ c = exec.Command(dockerBinary, "images", "-q", "-f", "dangling=true") |
|
| 209 |
+ out, _, err = runCommandWithOutput(c) |
|
| 210 |
+ if err != nil {
|
|
| 211 |
+ t.Fatalf("listing images failed with errors: %s, %v", out, err)
|
|
| 212 |
+ } |
|
| 213 |
+ |
|
| 214 |
+ if e, a := 1, strings.Count(out, imageId); e != a {
|
|
| 215 |
+ t.Fatalf("expected 1 dangling image, got %d: %s", a, out)
|
|
| 216 |
+ } |
|
| 217 |
+ |
|
| 218 |
+ logDone("images - dangling image only listed once")
|
|
| 219 |
+} |