2015-12-06 18:34:25 -05:00
|
|
|
package inspect
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"text/template"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Inspector defines an interface to implement to process elements
|
|
|
|
type Inspector interface {
|
|
|
|
Inspect(typedElement interface{}, rawElement []byte) error
|
|
|
|
Flush() error
|
|
|
|
}
|
|
|
|
|
|
|
|
// TemplateInspector uses a text template to inspect elements.
|
|
|
|
type TemplateInspector struct {
|
|
|
|
outputStream io.Writer
|
|
|
|
buffer *bytes.Buffer
|
|
|
|
tmpl *template.Template
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewTemplateInspector creates a new inspector with a template.
|
|
|
|
func NewTemplateInspector(outputStream io.Writer, tmpl *template.Template) Inspector {
|
|
|
|
return &TemplateInspector{
|
|
|
|
outputStream: outputStream,
|
|
|
|
buffer: new(bytes.Buffer),
|
|
|
|
tmpl: tmpl,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Inspect executes the inspect template.
|
|
|
|
// It decodes the raw element into a map if the initial execution fails.
|
|
|
|
// This allows docker cli to parse inspect structs injected with Swarm fields.
|
2015-12-07 22:04:38 -05:00
|
|
|
func (i *TemplateInspector) Inspect(typedElement interface{}, rawElement []byte) error {
|
2015-12-06 18:34:25 -05:00
|
|
|
buffer := new(bytes.Buffer)
|
|
|
|
if err := i.tmpl.Execute(buffer, typedElement); err != nil {
|
2015-12-07 22:04:38 -05:00
|
|
|
if rawElement == nil {
|
|
|
|
return fmt.Errorf("Template parsing error: %v", err)
|
2015-12-06 18:34:25 -05:00
|
|
|
}
|
2015-12-09 16:52:02 -05:00
|
|
|
return i.tryRawInspectFallback(rawElement, err)
|
2015-12-07 22:04:38 -05:00
|
|
|
}
|
|
|
|
i.buffer.Write(buffer.Bytes())
|
|
|
|
i.buffer.WriteByte('\n')
|
|
|
|
return nil
|
|
|
|
}
|
2015-12-06 18:34:25 -05:00
|
|
|
|
|
|
|
// Flush write the result of inspecting all elements into the output stream.
|
2015-12-07 22:04:38 -05:00
|
|
|
func (i *TemplateInspector) Flush() error {
|
2015-12-10 20:36:08 -05:00
|
|
|
if i.buffer.Len() == 0 {
|
|
|
|
_, err := io.WriteString(i.outputStream, "\n")
|
|
|
|
return err
|
|
|
|
}
|
2015-12-06 18:34:25 -05:00
|
|
|
_, err := io.Copy(i.outputStream, i.buffer)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// IndentedInspector uses a buffer to stop the indented representation of an element.
|
|
|
|
type IndentedInspector struct {
|
|
|
|
outputStream io.Writer
|
2015-12-07 22:04:38 -05:00
|
|
|
elements []interface{}
|
2015-12-17 20:46:48 -05:00
|
|
|
rawElements [][]byte
|
2015-12-06 18:34:25 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewIndentedInspector generates a new IndentedInspector.
|
|
|
|
func NewIndentedInspector(outputStream io.Writer) Inspector {
|
|
|
|
return &IndentedInspector{
|
|
|
|
outputStream: outputStream,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Inspect writes the raw element with an indented json format.
|
2015-12-17 20:46:48 -05:00
|
|
|
func (i *IndentedInspector) Inspect(typedElement interface{}, rawElement []byte) error {
|
|
|
|
if rawElement != nil {
|
|
|
|
i.rawElements = append(i.rawElements, rawElement)
|
|
|
|
} else {
|
|
|
|
i.elements = append(i.elements, typedElement)
|
|
|
|
}
|
2015-12-06 18:34:25 -05:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flush write the result of inspecting all elements into the output stream.
|
2015-12-07 22:04:38 -05:00
|
|
|
func (i *IndentedInspector) Flush() error {
|
2015-12-17 20:46:48 -05:00
|
|
|
if len(i.elements) == 0 && len(i.rawElements) == 0 {
|
2015-12-07 22:04:38 -05:00
|
|
|
_, err := io.WriteString(i.outputStream, "[]\n")
|
|
|
|
return err
|
2015-12-06 18:34:25 -05:00
|
|
|
}
|
|
|
|
|
2015-12-17 20:46:48 -05:00
|
|
|
var buffer io.Reader
|
|
|
|
if len(i.rawElements) > 0 {
|
|
|
|
bytesBuffer := new(bytes.Buffer)
|
|
|
|
bytesBuffer.WriteString("[")
|
|
|
|
for idx, r := range i.rawElements {
|
|
|
|
bytesBuffer.Write(r)
|
|
|
|
if idx < len(i.rawElements)-1 {
|
|
|
|
bytesBuffer.WriteString(",")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
bytesBuffer.WriteString("]")
|
|
|
|
indented := new(bytes.Buffer)
|
|
|
|
if err := json.Indent(indented, bytesBuffer.Bytes(), "", " "); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
buffer = indented
|
|
|
|
} else {
|
|
|
|
b, err := json.MarshalIndent(i.elements, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
buffer = bytes.NewReader(b)
|
2015-12-07 22:04:38 -05:00
|
|
|
}
|
|
|
|
|
2015-12-17 20:46:48 -05:00
|
|
|
if _, err := io.Copy(i.outputStream, buffer); err != nil {
|
2015-12-07 22:04:38 -05:00
|
|
|
return err
|
|
|
|
}
|
2015-12-17 20:46:48 -05:00
|
|
|
_, err := io.WriteString(i.outputStream, "\n")
|
2015-12-06 18:34:25 -05:00
|
|
|
return err
|
|
|
|
}
|