inspector.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. package inspect
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "text/template"
  8. )
  9. // Inspector defines an interface to implement to process elements
  10. type Inspector interface {
  11. Inspect(typedElement interface{}, rawElement []byte) error
  12. Flush() error
  13. }
  14. // TemplateInspector uses a text template to inspect elements.
  15. type TemplateInspector struct {
  16. outputStream io.Writer
  17. buffer *bytes.Buffer
  18. tmpl *template.Template
  19. }
  20. // NewTemplateInspector creates a new inspector with a template.
  21. func NewTemplateInspector(outputStream io.Writer, tmpl *template.Template) Inspector {
  22. return &TemplateInspector{
  23. outputStream: outputStream,
  24. buffer: new(bytes.Buffer),
  25. tmpl: tmpl,
  26. }
  27. }
  28. // Inspect executes the inspect template.
  29. // It decodes the raw element into a map if the initial execution fails.
  30. // This allows docker cli to parse inspect structs injected with Swarm fields.
  31. func (i *TemplateInspector) Inspect(typedElement interface{}, rawElement []byte) error {
  32. buffer := new(bytes.Buffer)
  33. if err := i.tmpl.Execute(buffer, typedElement); err != nil {
  34. if rawElement == nil {
  35. return fmt.Errorf("Template parsing error: %v", err)
  36. }
  37. return i.tryRawInspectFallback(rawElement, err)
  38. }
  39. i.buffer.Write(buffer.Bytes())
  40. i.buffer.WriteByte('\n')
  41. return nil
  42. }
  43. // Flush write the result of inspecting all elements into the output stream.
  44. func (i *TemplateInspector) Flush() error {
  45. if i.buffer.Len() == 0 {
  46. _, err := io.WriteString(i.outputStream, "\n")
  47. return err
  48. }
  49. _, err := io.Copy(i.outputStream, i.buffer)
  50. return err
  51. }
  52. // IndentedInspector uses a buffer to stop the indented representation of an element.
  53. type IndentedInspector struct {
  54. outputStream io.Writer
  55. elements []interface{}
  56. }
  57. // NewIndentedInspector generates a new IndentedInspector.
  58. func NewIndentedInspector(outputStream io.Writer) Inspector {
  59. return &IndentedInspector{
  60. outputStream: outputStream,
  61. }
  62. }
  63. // Inspect writes the raw element with an indented json format.
  64. func (i *IndentedInspector) Inspect(typedElement interface{}, _ []byte) error {
  65. i.elements = append(i.elements, typedElement)
  66. return nil
  67. }
  68. // Flush write the result of inspecting all elements into the output stream.
  69. func (i *IndentedInspector) Flush() error {
  70. if len(i.elements) == 0 {
  71. _, err := io.WriteString(i.outputStream, "[]\n")
  72. return err
  73. }
  74. buffer, err := json.MarshalIndent(i.elements, "", " ")
  75. if err != nil {
  76. return err
  77. }
  78. if _, err := io.Copy(i.outputStream, bytes.NewReader(buffer)); err != nil {
  79. return err
  80. }
  81. _, err = io.WriteString(i.outputStream, "\n")
  82. return err
  83. }