// FIXME: --viz and --tree are deprecated. Remove them in a future version. func (cli *DockerCli) WalkTree(noTrunc bool, images *engine.Table, byParent map[string]*engine.Table, prefix string, printNode func(cli *DockerCli, noTrunc bool, image *engine.Env, prefix string)) { length := images.Len() if length > 1 { for index, image := range images.Data { if index+1 == length { printNode(cli, noTrunc, image, prefix+"└─") if subimages, exists := byParent[image.Get("Id")]; exists { cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode) } } else { printNode(cli, noTrunc, image, prefix+"\u251C─") if subimages, exists := byParent[image.Get("Id")]; exists { cli.WalkTree(noTrunc, subimages, byParent, prefix+"\u2502 ", printNode) } } } } else { for _, image := range images.Data { printNode(cli, noTrunc, image, prefix+"└─") if subimages, exists := byParent[image.Get("Id")]; exists { cli.WalkTree(noTrunc, subimages, byParent, prefix+" ", printNode) } } } }
//TODO remove, used on < 1.5 in getContainersJSON func DisplayablePorts(ports *engine.Table) string { result := []string{} ports.SetKey("PublicPort") ports.Sort() for _, port := range ports.Data { if port.Get("IP") == "" { result = append(result, fmt.Sprintf("%d/%s", port.GetInt("PrivatePort"), port.Get("Type"))) } else { result = append(result, fmt.Sprintf("%s:%d->%d/%s", port.Get("IP"), port.GetInt("PublicPort"), port.GetInt("PrivatePort"), port.Get("Type"))) } } return strings.Join(result, ", ") }
// TODO remove, used on < 1.5 in getContainersJSON func DisplayablePorts(ports *engine.Table) string { var ( result = []string{} hostMappings = []string{} firstInGroupMap map[string]int lastInGroupMap map[string]int ) firstInGroupMap = make(map[string]int) lastInGroupMap = make(map[string]int) ports.SetKey("PrivatePort") ports.Sort() for _, port := range ports.Data { var ( current = port.GetInt("PrivatePort") portKey = port.Get("Type") firstInGroup int lastInGroup int ) if port.Get("IP") != "" { if port.GetInt("PublicPort") != current { hostMappings = append(hostMappings, fmt.Sprintf("%s:%d->%d/%s", port.Get("IP"), port.GetInt("PublicPort"), port.GetInt("PrivatePort"), port.Get("Type"))) continue } portKey = fmt.Sprintf("%s/%s", port.Get("IP"), port.Get("Type")) } firstInGroup = firstInGroupMap[portKey] lastInGroup = lastInGroupMap[portKey] if firstInGroup == 0 { firstInGroupMap[portKey] = current lastInGroupMap[portKey] = current continue } if current == (lastInGroup + 1) { lastInGroupMap[portKey] = current continue } result = append(result, FormGroup(portKey, firstInGroup, lastInGroup)) firstInGroupMap[portKey] = current lastInGroupMap[portKey] = current } for portKey, firstInGroup := range firstInGroupMap { result = append(result, FormGroup(portKey, firstInGroup, lastInGroupMap[portKey])) } result = append(result, hostMappings...) return strings.Join(result, ", ") }
func getContainersJSON(eng *engine.Engine, version version.Version, w http.ResponseWriter, r *http.Request, vars map[string]string) error { if err := parseForm(r); err != nil { return err } var ( err error outs *engine.Table job = eng.Job("containers") ) job.Setenv("all", r.Form.Get("all")) job.Setenv("size", r.Form.Get("size")) job.Setenv("since", r.Form.Get("since")) job.Setenv("before", r.Form.Get("before")) job.Setenv("limit", r.Form.Get("limit")) job.Setenv("filters", r.Form.Get("filters")) if version.GreaterThanOrEqualTo("1.5") { streamJSON(job, w, false) } else if outs, err = job.Stdout.AddTable(); err != nil { return err } if err = job.Run(); err != nil { return err } if version.LessThan("1.5") { // Convert to legacy format for _, out := range outs.Data { ports := engine.NewTable("", 0) ports.ReadListFrom([]byte(out.Get("Ports"))) out.Set("Ports", api.DisplayablePorts(ports)) } w.Header().Set("Content-Type", "application/json") if _, err = outs.WriteListTo(w); err != nil { return err } } return nil }
// FIXME: make this private and use the job instead func (daemon *Daemon) DeleteImage(eng *engine.Engine, name string, imgs *engine.Table, first, force, noprune bool) error { var ( repoName, tag string tags = []string{} ) // FIXME: please respect DRY and centralize repo+tag parsing in a single central place! -- shykes repoName, tag = parsers.ParseRepositoryTag(name) if tag == "" { tag = graph.DEFAULTTAG } if name == "" { return fmt.Errorf("Image name can not be blank") } img, err := daemon.Repositories().LookupImage(name) if err != nil { if r, _ := daemon.Repositories().Get(repoName); r != nil { return fmt.Errorf("No such image: %s:%s", repoName, tag) } return fmt.Errorf("No such image: %s", name) } if strings.Contains(img.ID, name) { repoName = "" tag = "" } byParents, err := daemon.Graph().ByParent() if err != nil { return err } repos := daemon.Repositories().ByID()[img.ID] //If delete by id, see if the id belong only to one repository if repoName == "" { for _, repoAndTag := range repos { parsedRepo, parsedTag := parsers.ParseRepositoryTag(repoAndTag) if repoName == "" || repoName == parsedRepo { repoName = parsedRepo if parsedTag != "" { tags = append(tags, parsedTag) } } else if repoName != parsedRepo && !force && first { // the id belongs to multiple repos, like base:latest and user:test, // in that case return conflict return fmt.Errorf("Conflict, cannot delete image %s because it is tagged in multiple repositories, use -f to force", name) } } } else { tags = append(tags, tag) } if !first && len(tags) > 0 { return nil } if len(repos) <= 1 { if err := daemon.canDeleteImage(img.ID, force); err != nil { return err } } // Untag the current image for _, tag := range tags { tagDeleted, err := daemon.Repositories().Delete(repoName, tag) if err != nil { return err } if tagDeleted { out := &engine.Env{} out.Set("Untagged", repoName+":"+tag) imgs.Add(out) eng.Job("log", "untag", img.ID, "").Run() } } tags = daemon.Repositories().ByID()[img.ID] if (len(tags) <= 1 && repoName == "") || len(tags) == 0 { if len(byParents[img.ID]) == 0 { if err := daemon.Repositories().DeleteAll(img.ID); err != nil { return err } if err := daemon.Graph().Delete(img.ID); err != nil { return err } out := &engine.Env{} out.SetJson("Deleted", img.ID) imgs.Add(out) eng.Job("log", "delete", img.ID, "").Run() if img.Parent != "" && !noprune { err := daemon.DeleteImage(eng, img.Parent, imgs, false, force, noprune) if first { return err } } } } return nil }
func (srv *Server) DeleteImage(name string, imgs *engine.Table, first, force, noprune bool) error { var ( repoName, tag string tags = []string{} tagDeleted bool ) repoName, tag = parsers.ParseRepositoryTag(name) if tag == "" { tag = graph.DEFAULTTAG } img, err := srv.daemon.Repositories().LookupImage(name) if err != nil { if r, _ := srv.daemon.Repositories().Get(repoName); r != nil { return fmt.Errorf("No such image: %s:%s", repoName, tag) } return fmt.Errorf("No such image: %s", name) } if strings.Contains(img.ID, name) { repoName = "" tag = "" } byParents, err := srv.daemon.Graph().ByParent() if err != nil { return err } //If delete by id, see if the id belong only to one repository if repoName == "" { for _, repoAndTag := range srv.daemon.Repositories().ByID()[img.ID] { parsedRepo, parsedTag := parsers.ParseRepositoryTag(repoAndTag) if repoName == "" || repoName == parsedRepo { repoName = parsedRepo if parsedTag != "" { tags = append(tags, parsedTag) } } else if repoName != parsedRepo && !force { // the id belongs to multiple repos, like base:latest and user:test, // in that case return conflict return fmt.Errorf("Conflict, cannot delete image %s because it is tagged in multiple repositories, use -f to force", name) } } } else { tags = append(tags, tag) } if !first && len(tags) > 0 { return nil } //Untag the current image for _, tag := range tags { tagDeleted, err = srv.daemon.Repositories().Delete(repoName, tag) if err != nil { return err } if tagDeleted { out := &engine.Env{} out.Set("Untagged", repoName+":"+tag) imgs.Add(out) srv.LogEvent("untag", img.ID, "") } } tags = srv.daemon.Repositories().ByID()[img.ID] if (len(tags) <= 1 && repoName == "") || len(tags) == 0 { if len(byParents[img.ID]) == 0 { if err := srv.canDeleteImage(img.ID, force, tagDeleted); err != nil { return err } if err := srv.daemon.Repositories().DeleteAll(img.ID); err != nil { return err } if err := srv.daemon.Graph().Delete(img.ID); err != nil { return err } out := &engine.Env{} out.Set("Deleted", img.ID) imgs.Add(out) srv.LogEvent("delete", img.ID, "") if img.Parent != "" && !noprune { err := srv.DeleteImage(img.Parent, imgs, false, force, noprune) if first { return err } } } } return nil }