// Test that an image can be deleted by its shorthand prefix func TestDeletePrefix(t *testing.T) { graph := tempGraph(t) defer os.RemoveAll(graph.Root) img := createTestImage(graph, t) if err := graph.Delete(utils.TruncateId(img.Id)); err != nil { t.Fatal(err) } assertNImages(graph, t, 0) }
func (srv *Server) ImagesViz(out io.Writer) error { images, _ := srv.runtime.graph.All() if images == nil { return nil } out.Write([]byte("digraph docker {\n")) var ( parentImage *Image err error ) for _, image := range images { parentImage, err = image.GetParent() if err != nil { return fmt.Errorf("Error while getting parent image: %v", err) } if parentImage != nil { out.Write([]byte(" \"" + parentImage.ShortId() + "\" -> \"" + image.ShortId() + "\"\n")) } else { out.Write([]byte(" base -> \"" + image.ShortId() + "\" [style=invis]\n")) } } reporefs := make(map[string][]string) for name, repository := range srv.runtime.repositories.Repositories { for tag, id := range repository { reporefs[utils.TruncateId(id)] = append(reporefs[utils.TruncateId(id)], fmt.Sprintf("%s:%s", name, tag)) } } for id, repos := range reporefs { out.Write([]byte(" \"" + id + "\" [label=\"" + id + "\\n" + strings.Join(repos, "\\n") + "\",shape=box,fillcolor=\"paleturquoise\",style=\"filled,rounded\"];\n")) } out.Write([]byte(" base [style=invisible]\n}\n")) return nil }
func (cli *DockerCli) CmdPs(args ...string) error { cmd := Subcmd("ps", "[OPTIONS]", "List containers") quiet := cmd.Bool("q", false, "Only display numeric IDs") all := cmd.Bool("a", false, "Show all containers. Only running containers are shown by default.") noTrunc := cmd.Bool("notrunc", false, "Don't truncate output") nLatest := cmd.Bool("l", false, "Show only the latest created container, include non-running ones.") since := cmd.String("sinceId", "", "Show only containers created since Id, include non-running ones.") before := cmd.String("beforeId", "", "Show only container created before Id, include non-running ones.") last := cmd.Int("n", -1, "Show n last created containers, include non-running ones.") if err := cmd.Parse(args); err != nil { return nil } v := url.Values{} if *last == -1 && *nLatest { *last = 1 } if *all { v.Set("all", "1") } if *last != -1 { v.Set("limit", strconv.Itoa(*last)) } if *since != "" { v.Set("since", *since) } if *before != "" { v.Set("before", *before) } body, _, err := cli.call("GET", "/containers/json?"+v.Encode(), nil) if err != nil { return err } var outs []ApiContainers err = json.Unmarshal(body, &outs) if err != nil { return err } w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0) if !*quiet { fmt.Fprintln(w, "ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS") } for _, out := range outs { if !*quiet { if *noTrunc { fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\n", out.Id, out.Image, out.Command, utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports) } else { fmt.Fprintf(w, "%s\t%s\t%s\t%s ago\t%s\t%s\n", utils.TruncateId(out.Id), out.Image, utils.Trunc(out.Command, 20), utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0))), out.Status, out.Ports) } } else { if *noTrunc { fmt.Fprintln(w, out.Id) } else { fmt.Fprintln(w, utils.TruncateId(out.Id)) } } } if !*quiet { w.Flush() } return nil }
func (cli *DockerCli) CmdImages(args ...string) error { cmd := Subcmd("images", "[OPTIONS] [NAME]", "List images") quiet := cmd.Bool("q", false, "only show numeric IDs") all := cmd.Bool("a", false, "show all images") noTrunc := cmd.Bool("notrunc", false, "Don't truncate output") flViz := cmd.Bool("viz", false, "output graph in graphviz format") if err := cmd.Parse(args); err != nil { return nil } if cmd.NArg() > 1 { cmd.Usage() return nil } if *flViz { body, _, err := cli.call("GET", "/images/viz", false) if err != nil { return err } fmt.Printf("%s", body) } else { v := url.Values{} if cmd.NArg() == 1 { v.Set("filter", cmd.Arg(0)) } if *all { v.Set("all", "1") } body, _, err := cli.call("GET", "/images/json?"+v.Encode(), nil) if err != nil { return err } var outs []ApiImages err = json.Unmarshal(body, &outs) if err != nil { return err } w := tabwriter.NewWriter(os.Stdout, 20, 1, 3, ' ', 0) if !*quiet { fmt.Fprintln(w, "REPOSITORY\tTAG\tID\tCREATED") } for _, out := range outs { if out.Repository == "" { out.Repository = "<none>" } if out.Tag == "" { out.Tag = "<none>" } if !*quiet { fmt.Fprintf(w, "%s\t%s\t", out.Repository, out.Tag) if *noTrunc { fmt.Fprintf(w, "%s\t", out.Id) } else { fmt.Fprintf(w, "%s\t", utils.TruncateId(out.Id)) } fmt.Fprintf(w, "%s ago\n", utils.HumanDuration(time.Now().Sub(time.Unix(out.Created, 0)))) } else { if *noTrunc { fmt.Fprintln(w, out.Id) } else { fmt.Fprintln(w, utils.TruncateId(out.Id)) } } } if !*quiet { w.Flush() } } return nil }
// ShortId returns a shorthand version of the container's id for convenience. // A collision with other container shorthands is very unlikely, but possible. // In case of a collision a lookup with Runtime.Get() will fail, and the caller // will need to use a langer prefix, or the full-length container Id. func (container *Container) ShortId() string { return utils.TruncateId(container.Id) }
func (image *Image) ShortId() string { return utils.TruncateId(image.Id) }
func (store *TagStore) ImageName(id string) string { if names, exists := store.ById()[id]; exists && len(names) > 0 { return names[0] } return utils.TruncateId(id) }