From 2369da5d31830e5cd3e1a13857a686365875ae61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20M=C3=ADchal?= Date: Mon, 22 Mar 2021 14:51:16 +0100 Subject: [PATCH] cmd/list: Filter images/containers using labels Instead of executing 'podman ps|images' several times in a row, call them only once and get output with all images/containers. Then, filter out the JSON using labels and keep images/containers only with matching labels. This simplifies the code significantly and cuts down the execution time of 'toolbox list'. The speed gain is noticeable: - the system has 5 images and 10 containers Before patch: ~1.45s After patch: ~0.85s --- src/cmd/list.go | 103 +++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/src/cmd/list.go b/src/cmd/list.go index 43cf26a..51c6f9e 100644 --- a/src/cmd/list.go +++ b/src/cmd/list.go @@ -51,6 +51,12 @@ var ( onlyContainers bool onlyImages bool } + + // toolboxLabels holds labels used by containers/images that mark them as compatible with Toolbox + toolboxLabels = map[string]string{ + "com.github.debarshiray.toolbox": "true", + "com.github.containers.toolbox": "true", + } ) var listCmd = &cobra.Command{ @@ -123,35 +129,22 @@ func list(cmd *cobra.Command, args []string) error { } func getContainers() ([]toolboxContainer, error) { - logrus.Debug("Fetching containers with label=com.github.containers.toolbox=true") - args := []string{"--all", "--filter", "label=com.github.containers.toolbox=true"} - containers_old, err := podman.GetContainers(args...) - if err != nil { - return nil, fmt.Errorf("failed to list containers with label=com.github.containers.toolbox=true: %w", err) - } - - logrus.Debug("Fetching containers with label=com.github.debarshiray.toolbox=true") - args = []string{"--all", "--filter", "label=com.github.debarshiray.toolbox=true"} - containers_new, err := podman.GetContainers(args...) - if err != nil { - return nil, fmt.Errorf("failed to list containers with label=com.github.debarshiray.toolbox=true: %w", err) - } - + var err error + var args []string var containers []map[string]interface{} - if podman.CheckVersion("2.0.0") { - containers = utils.JoinJSON("Id", containers_old, containers_new) - containers = utils.SortJSON(containers, "Names", true) - } else { - containers = utils.JoinJSON("ID", containers_old, containers_new) - containers = utils.SortJSON(containers, "Names", false) + var toolboxContainers []toolboxContainer + + logrus.Debug("Fetching all containers") + args = []string{"--all", "--sort", "names"} + containers, err = podman.GetContainers(args...) + if err != nil { + return nil, fmt.Errorf("failed to get containers: %w", err) } - // This section is a temporary solution that is here to prevent a major - // redesign of the way how toolbox containers are fetched. - // Remove this in Toolbox v0.2.0 - var toolboxContainers []toolboxContainer for _, container := range containers { var c toolboxContainer + var isToolboxContainer bool = false + containerJSON, err := json.Marshal(container) if err != nil { logrus.Errorf("failed to marshal container: %v", err) @@ -163,7 +156,17 @@ func getContainers() ([]toolboxContainer, error) { logrus.Errorf("failed to unmarshal container: %v", err) continue } - toolboxContainers = append(toolboxContainers, c) + + for label := range toolboxLabels { + if _, ok := c.Labels[label]; ok { + isToolboxContainer = true + break + } + } + + if isToolboxContainer { + toolboxContainers = append(toolboxContainers, c) + } } return toolboxContainers, nil @@ -191,38 +194,22 @@ func listHelp(cmd *cobra.Command, args []string) { } func getImages() ([]toolboxImage, error) { - logrus.Debug("Fetching images with label=com.github.containers.toolbox=true") - args := []string{"--filter", "label=com.github.containers.toolbox=true"} - images_old, err := podman.GetImages(args...) - if err != nil { - return nil, errors.New("failed to list images with label=com.github.containers.toolbox=true") - } - - logrus.Debug("Fetching images with label=com.github.debarshiray.toolbox=true") - args = []string{"--filter", "label=com.github.debarshiray.toolbox=true"} - images_new, err := podman.GetImages(args...) - if err != nil { - return nil, errors.New("failed to list images with com.github.debarshiray.toolbox=true") - } - + var err error + var args []string var images []map[string]interface{} - if podman.CheckVersion("2.0.0") { - images = utils.JoinJSON("Id", images_old, images_new) - images = utils.SortJSON(images, "Names", true) - } else if podman.CheckVersion("1.8.3") { - images = utils.JoinJSON("ID", images_old, images_new) - images = utils.SortJSON(images, "Names", true) - } else { - images = utils.JoinJSON("id", images_old, images_new) - images = utils.SortJSON(images, "names", true) + var toolboxImages []toolboxImage + + logrus.Debug("Fetching all images") + args = []string{"--sort", "repository"} + images, err = podman.GetImages(args...) + if err != nil { + return nil, fmt.Errorf("failed to get images: %w", err) } - // This section is a temporary solution that is here to prevent a major - // redesign of the way how toolbox images are fetched. - // Remove this in Toolbox v0.2.0 - var toolboxImages []toolboxImage for _, image := range images { var i toolboxImage + var isToolboxImage bool = false + imageJSON, err := json.Marshal(image) if err != nil { logrus.Errorf("failed to marshal toolbox image: %v", err) @@ -234,7 +221,17 @@ func getImages() ([]toolboxImage, error) { logrus.Errorf("failed to unmarshal toolbox image: %v", err) continue } - toolboxImages = append(toolboxImages, i) + + for label := range toolboxLabels { + if _, ok := i.Labels[label]; ok { + isToolboxImage = true + break + } + } + + if isToolboxImage { + toolboxImages = append(toolboxImages, i) + } } return toolboxImages, nil