github.com/sijibomii/docker@v0.0.0-20231230191044-5cf6ca554647/api/client/inspect/inspector.go (about) 1 package inspect 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "text/template" 9 ) 10 11 // Inspector defines an interface to implement to process elements 12 type Inspector interface { 13 Inspect(typedElement interface{}, rawElement []byte) error 14 Flush() error 15 } 16 17 // TemplateInspector uses a text template to inspect elements. 18 type TemplateInspector struct { 19 outputStream io.Writer 20 buffer *bytes.Buffer 21 tmpl *template.Template 22 } 23 24 // NewTemplateInspector creates a new inspector with a template. 25 func NewTemplateInspector(outputStream io.Writer, tmpl *template.Template) Inspector { 26 return &TemplateInspector{ 27 outputStream: outputStream, 28 buffer: new(bytes.Buffer), 29 tmpl: tmpl, 30 } 31 } 32 33 // Inspect executes the inspect template. 34 // It decodes the raw element into a map if the initial execution fails. 35 // This allows docker cli to parse inspect structs injected with Swarm fields. 36 func (i *TemplateInspector) Inspect(typedElement interface{}, rawElement []byte) error { 37 buffer := new(bytes.Buffer) 38 if err := i.tmpl.Execute(buffer, typedElement); err != nil { 39 if rawElement == nil { 40 return fmt.Errorf("Template parsing error: %v", err) 41 } 42 return i.tryRawInspectFallback(rawElement, err) 43 } 44 i.buffer.Write(buffer.Bytes()) 45 i.buffer.WriteByte('\n') 46 return nil 47 } 48 49 // Flush write the result of inspecting all elements into the output stream. 50 func (i *TemplateInspector) Flush() error { 51 if i.buffer.Len() == 0 { 52 _, err := io.WriteString(i.outputStream, "\n") 53 return err 54 } 55 _, err := io.Copy(i.outputStream, i.buffer) 56 return err 57 } 58 59 // IndentedInspector uses a buffer to stop the indented representation of an element. 60 type IndentedInspector struct { 61 outputStream io.Writer 62 elements []interface{} 63 rawElements [][]byte 64 } 65 66 // NewIndentedInspector generates a new IndentedInspector. 67 func NewIndentedInspector(outputStream io.Writer) Inspector { 68 return &IndentedInspector{ 69 outputStream: outputStream, 70 } 71 } 72 73 // Inspect writes the raw element with an indented json format. 74 func (i *IndentedInspector) Inspect(typedElement interface{}, rawElement []byte) error { 75 if rawElement != nil { 76 i.rawElements = append(i.rawElements, rawElement) 77 } else { 78 i.elements = append(i.elements, typedElement) 79 } 80 return nil 81 } 82 83 // Flush write the result of inspecting all elements into the output stream. 84 func (i *IndentedInspector) Flush() error { 85 if len(i.elements) == 0 && len(i.rawElements) == 0 { 86 _, err := io.WriteString(i.outputStream, "[]\n") 87 return err 88 } 89 90 var buffer io.Reader 91 if len(i.rawElements) > 0 { 92 bytesBuffer := new(bytes.Buffer) 93 bytesBuffer.WriteString("[") 94 for idx, r := range i.rawElements { 95 bytesBuffer.Write(r) 96 if idx < len(i.rawElements)-1 { 97 bytesBuffer.WriteString(",") 98 } 99 } 100 bytesBuffer.WriteString("]") 101 indented := new(bytes.Buffer) 102 if err := json.Indent(indented, bytesBuffer.Bytes(), "", " "); err != nil { 103 return err 104 } 105 buffer = indented 106 } else { 107 b, err := json.MarshalIndent(i.elements, "", " ") 108 if err != nil { 109 return err 110 } 111 buffer = bytes.NewReader(b) 112 } 113 114 if _, err := io.Copy(i.outputStream, buffer); err != nil { 115 return err 116 } 117 _, err := io.WriteString(i.outputStream, "\n") 118 return err 119 }