Open mikebski opened 6 years ago
TLDR; docker inspect
deals with JSON output and thus JSON output templates, versus the formatting strings you'd expect from other commands (such as docker stats
I think the confusion stems from docker inspect
not having the same --format
functionality as other traditional command such as docker stats
which you mentioned. When formatting command output commands provide a format context and a writer. Stats for example:
func NewStatsFormat(source, osType string) Format {
if source == TableFormatKey {
if osType == winOSType {
return Format(winDefaultStatsTableFormat)
}
return Format(defaultStatsTableFormat)
}
return Format(source)
}
https://github.com/docker/cli/blob/master/cli/command/formatter/stats.go#L102
So based on various constraints it either returns a default format string (if you just pass in table
as the format string for example) or just passes the format string provided as-is. Then you have the writer which renders the template given the format:
func ContainerStatsWrite(ctx Context, containerStats []StatsEntry, osType string, trunc bool) error {
render := func(format func(subContext subContext) error) error {
for _, cstats := range containerStats {
containerStatsCtx := &containerStatsContext{
s: cstats,
os: osType,
trunc: trunc,
}
if err := format(containerStatsCtx); err != nil {
return err
}
}
return nil
}
memUsage := memUseHeader
if osType == winOSType {
memUsage = winMemUseHeader
}
containerStatsCtx := containerStatsContext{}
containerStatsCtx.header = map[string]string{
"Container": containerHeader,
"Name": nameHeader,
"ID": containerIDHeader,
"CPUPerc": cpuPercHeader,
"MemUsage": memUsage,
"MemPerc": memPercHeader,
"NetIO": netIOHeader,
"BlockIO": blockIOHeader,
"PIDs": pidsHeader,
}
containerStatsCtx.os = osType
return ctx.Write(&containerStatsCtx, render)
}
https://github.com/docker/cli/blob/master/cli/command/formatter/stats.go#L118
Now with the inspect command it takes a different path:
// ServiceInspectWrite renders the context for a list of services
func ServiceInspectWrite(ctx Context, refs []string, getRef, getNetwork inspect.GetRefFunc) error {
if ctx.Format != serviceInspectPrettyTemplate {
return inspect.Inspect(ctx.Output, refs, string(ctx.Format), getRef)
}
https://github.com/docker/cli/blob/master/cli/command/formatter/service.go#L170
Unless you have pretty format enabled it does an inspect.Inspect
call:
// NewTemplateInspectorFromString creates a new TemplateInspector from a string
// which is compiled into a template.
func NewTemplateInspectorFromString(out io.Writer, tmplStr string) (Inspector, error) {
if tmplStr == "" {
return NewIndentedInspector(out), nil
}
tmpl, err := templates.Parse(tmplStr)
if err != nil {
return nil, errors.Errorf("Template parsing error: %s", err)
}
return NewTemplateInspector(out, tmpl), nil
}
// -------- SNIP ------------
func Inspect(out io.Writer, references []string, tmplStr string, getRef GetRefFunc) error {
inspector, err := NewTemplateInspectorFromString(out, tmplStr)
This in turn uses a different string format including different base functions:
var basicFunctions = template.FuncMap{
"json": func(v interface{}) string {
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
enc.Encode(v)
// Remove the trailing new line added by the encoder
return strings.TrimSpace(buf.String())
},
"split": strings.Split,
"join": strings.Join,
"title": strings.Title,
"lower": strings.ToLower,
"upper": strings.ToUpper,
"pad": padWithSpace,
"truncate": truncateWithLength,
}
https://github.com/docker/cli/blob/master/templates/templates.go#L12
Which is essentially why table
isn't working as expected and coming back as raw. That said it might be good to have a --template-format
instead to make it a bit less confusing.
docker service inspect --format 'table {{.Spec.Name}}\t{{range .Endpoint.VirtualIPs}}{{.Addr}} {{end}}' $(docker service ls -q)
This is not printing a table, it's printing:Steps to reproduce the issue:
docker service create ngnix
will workdocker service inspect --format 'table {{.Spec.Name}}\t{{range .Endpoint.VirtualIPs}}{{.Addr}} {{end}}' $(docker service ls -q)
Describe the results you received:
*Note service has no IP address, that's fine here
Describe the results you expected:
Table output similar to
docker stats
with 2 columnsOutput of
docker version
:Output of
docker info
:Additional environment details (AWS, VirtualBox, physical, etc.):
Mac laptop