github.com/walkingsparrow/docker@v1.4.2-0.20151218153551-b708a2249bfa/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  }
    64  
    65  // NewIndentedInspector generates a new IndentedInspector.
    66  func NewIndentedInspector(outputStream io.Writer) Inspector {
    67  	return &IndentedInspector{
    68  		outputStream: outputStream,
    69  	}
    70  }
    71  
    72  // Inspect writes the raw element with an indented json format.
    73  func (i *IndentedInspector) Inspect(typedElement interface{}, _ []byte) error {
    74  	i.elements = append(i.elements, typedElement)
    75  	return nil
    76  }
    77  
    78  // Flush write the result of inspecting all elements into the output stream.
    79  func (i *IndentedInspector) Flush() error {
    80  	if len(i.elements) == 0 {
    81  		_, err := io.WriteString(i.outputStream, "[]\n")
    82  		return err
    83  	}
    84  
    85  	buffer, err := json.MarshalIndent(i.elements, "", "    ")
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	if _, err := io.Copy(i.outputStream, bytes.NewReader(buffer)); err != nil {
    91  		return err
    92  	}
    93  	_, err = io.WriteString(i.outputStream, "\n")
    94  	return err
    95  }