cmd/list: Implement the list command

Go's text/tabwriter package isn't aware of the ANSI Select Graphic
Rendition (or SGR) escape sequences to change the terminal's
foreground colour [1,2]. Using the sequences disrupt the alignment of
the columns in the tabbed output.

Therefore, unlike the existing POSIX shell implementation, running
containers aren't marked in green in the Go version.

[1] https://en.wikipedia.org/wiki/ANSI_escape_code
[2] https://github.com/golang/go/issues/12073

https://github.com/containers/toolbox/pull/318
This commit is contained in:
Harry Míchal 2020-04-08 14:04:57 +02:00 committed by Debarshi Ray
parent f4d129ab4d
commit c30d5549b6
1 changed files with 143 additions and 0 deletions

View File

@ -17,10 +17,14 @@
package cmd package cmd
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"text/tabwriter"
"github.com/containers/toolbox/pkg/podman"
"github.com/containers/toolbox/pkg/utils" "github.com/containers/toolbox/pkg/utils"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -57,9 +61,69 @@ func init() {
} }
func list(cmd *cobra.Command, args []string) error { func list(cmd *cobra.Command, args []string) error {
if utils.IsInsideContainer() {
if !utils.IsInsideToolboxContainer() {
return errors.New("this is not a toolbox container")
}
if _, err := utils.ForwardToHost(); err != nil {
return err
}
return nil
}
lsContainers := true
lsImages := true
if !listFlags.onlyContainers && listFlags.onlyImages {
lsContainers = false
} else if listFlags.onlyContainers && !listFlags.onlyImages {
lsImages = false
}
var images []map[string]interface{}
var containers []map[string]interface{}
var err error
if lsImages {
images, err = listImages()
if err != nil {
return err
}
}
if lsContainers {
containers, err = listContainers()
if err != nil {
return err
}
}
listOutput(images, containers)
return nil return nil
} }
func listContainers() ([]map[string]interface{}, error) {
logrus.Debug("Fetching containers with label=com.redhat.component=fedora-toolbox")
args := []string{"--all", "--filter", "label=com.redhat.component=fedora-toolbox"}
containers_old, err := podman.GetContainers(args...)
if err != nil {
return nil, errors.New("failed to list containers with com.redhat.component=fedora-toolbox")
}
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, errors.New("failed to list containers with label=com.github.debarshiray.toolbox=true")
}
containers := utils.JoinJSON("ID", containers_old, containers_new)
containers = utils.SortJSON(containers, "Names", false)
return containers, nil
}
func listHelp(cmd *cobra.Command, args []string) { func listHelp(cmd *cobra.Command, args []string) {
if utils.IsInsideContainer() { if utils.IsInsideContainer() {
if !utils.IsInsideToolboxContainer() { if !utils.IsInsideToolboxContainer() {
@ -80,3 +144,82 @@ func listHelp(cmd *cobra.Command, args []string) {
return return
} }
} }
func listImages() ([]map[string]interface{}, error) {
logrus.Debug("Fetching images with label=com.redhat.component=fedora-toolbox")
args := []string{"--filter", "label=com.redhat.component=fedora-toolbox"}
images_old, err := podman.GetImages(args...)
if err != nil {
return nil, errors.New("failed to list images with com.redhat.component=fedora-toolbox")
}
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 images []map[string]interface{}
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)
}
return images, nil
}
func listOutput(images, containers []map[string]interface{}) {
if len(images) != 0 {
writer := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(writer, "%s\t%s\t%s\n", "IMAGE ID", "IMAGE NAME", "CREATED")
var idKey, nameKey, createdKey string
if podman.CheckVersion("1.8.3") {
idKey = "ID"
nameKey = "Names"
createdKey = "Created"
} else {
idKey = "id"
nameKey = "names"
createdKey = "created"
}
for _, image := range images {
id := utils.ShortID(image[idKey].(string))
name := image[nameKey].([]interface{})[0].(string)
created := image[createdKey].(string)
fmt.Fprintf(writer, "%s\t%s\t%s\n", id, name, created)
}
writer.Flush()
}
if len(images) != 0 && len(containers) != 0 {
fmt.Println()
}
if len(containers) != 0 {
writer := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(writer,
"%s\t%s\t%s\t%s\t%s\n",
"CONTAINER ID",
"CONTAINER NAME",
"CREATED",
"STATUS",
"IMAGE NAME")
for _, container := range containers {
id := container["ID"].(string)[:12]
name := container["Names"].(string)
created := container["Created"].(string)
status := container["Status"].(string)
imageName := container["Image"].(string)
fmt.Fprintf(writer, "%s\t%s\t%s\t%s\t%s\n", id, name, created, status, imageName)
}
writer.Flush()
}
}