106 lines
2.2 KiB
Go
106 lines
2.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
type Container struct {
|
||
|
Id string
|
||
|
Image string
|
||
|
Names []string
|
||
|
Ports []map[string]interface{}
|
||
|
Created int64
|
||
|
Status string
|
||
|
Command string
|
||
|
}
|
||
|
|
||
|
type ContainersCommand struct {
|
||
|
Dot bool `short:"d" long:"dot" description:"Show container information as Graphviz dot."`
|
||
|
NoTruncate bool `short:"n" long:"no-trunc" description:"Don't truncate the container IDs."`
|
||
|
}
|
||
|
|
||
|
var containersCommand ContainersCommand
|
||
|
|
||
|
func (x *ContainersCommand) Execute(args []string) error {
|
||
|
|
||
|
// read in stdin
|
||
|
stdin, err := ioutil.ReadAll(os.Stdin)
|
||
|
if err != nil {
|
||
|
return fmt.Errorf("error reading all input", err)
|
||
|
}
|
||
|
|
||
|
containers, err := parseContainersJSON(stdin)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if containersCommand.Dot {
|
||
|
fmt.Printf(jsonContainersToDot(containers))
|
||
|
} else {
|
||
|
return fmt.Errorf("Please specify --dot")
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func parseContainersJSON(rawJSON []byte) (*[]Container, error) {
|
||
|
|
||
|
var containers []Container
|
||
|
err := json.Unmarshal(rawJSON, &containers)
|
||
|
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("Error reading JSON: ", err)
|
||
|
}
|
||
|
|
||
|
return &containers, nil
|
||
|
}
|
||
|
|
||
|
func jsonContainersToDot(containers *[]Container) string {
|
||
|
|
||
|
var buffer bytes.Buffer
|
||
|
buffer.WriteString("digraph docker {\n")
|
||
|
|
||
|
for _, container := range *containers {
|
||
|
|
||
|
var containerName string
|
||
|
|
||
|
for _, name := range container.Names {
|
||
|
if strings.Count(name, "/") == 1 {
|
||
|
containerName = name[1:]
|
||
|
}
|
||
|
}
|
||
|
for _, name := range container.Names {
|
||
|
nameParts := strings.Split(name, "/")
|
||
|
if len(nameParts) > 2 {
|
||
|
buffer.WriteString(fmt.Sprintf(" \"%s\" -> \"%s\" [label = \" %s\" ]\n", containerName, nameParts[1], nameParts[len(nameParts)-1]))
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var containerBackground string
|
||
|
if strings.Contains(container.Status, "Exited") {
|
||
|
containerBackground = "lightgrey"
|
||
|
} else {
|
||
|
containerBackground = "paleturquoise"
|
||
|
}
|
||
|
|
||
|
buffer.WriteString(fmt.Sprintf(" \"%s\" [label=\"%s\\n%s\",shape=box,fillcolor=\"%s\",style=\"filled,rounded\"];\n", containerName, containerName, truncate(container.Id), containerBackground))
|
||
|
}
|
||
|
|
||
|
buffer.WriteString("}\n")
|
||
|
|
||
|
return buffer.String()
|
||
|
}
|
||
|
|
||
|
func init() {
|
||
|
parser.AddCommand("containers",
|
||
|
"Visualize docker containers.",
|
||
|
"",
|
||
|
&containersCommand)
|
||
|
}
|