github.com/jandre/docker@v1.7.0/pkg/streamformatter/streamformatter.go (about) 1 package streamformatter 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 8 "github.com/docker/docker/pkg/jsonmessage" 9 ) 10 11 type StreamFormatter struct { 12 json bool 13 } 14 15 // NewStreamFormatter returns a simple StreamFormatter 16 func NewStreamFormatter() *StreamFormatter { 17 return &StreamFormatter{} 18 } 19 20 // NewJSONStreamFormatter returns a StreamFormatter configured to stream json 21 func NewJSONStreamFormatter() *StreamFormatter { 22 return &StreamFormatter{true} 23 } 24 25 const streamNewline = "\r\n" 26 27 var streamNewlineBytes = []byte(streamNewline) 28 29 func (sf *StreamFormatter) FormatStream(str string) []byte { 30 if sf.json { 31 b, err := json.Marshal(&jsonmessage.JSONMessage{Stream: str}) 32 if err != nil { 33 return sf.FormatError(err) 34 } 35 return append(b, streamNewlineBytes...) 36 } 37 return []byte(str + "\r") 38 } 39 40 func (sf *StreamFormatter) FormatStatus(id, format string, a ...interface{}) []byte { 41 str := fmt.Sprintf(format, a...) 42 if sf.json { 43 b, err := json.Marshal(&jsonmessage.JSONMessage{ID: id, Status: str}) 44 if err != nil { 45 return sf.FormatError(err) 46 } 47 return append(b, streamNewlineBytes...) 48 } 49 return []byte(str + streamNewline) 50 } 51 52 func (sf *StreamFormatter) FormatError(err error) []byte { 53 if sf.json { 54 jsonError, ok := err.(*jsonmessage.JSONError) 55 if !ok { 56 jsonError = &jsonmessage.JSONError{Message: err.Error()} 57 } 58 if b, err := json.Marshal(&jsonmessage.JSONMessage{Error: jsonError, ErrorMessage: err.Error()}); err == nil { 59 return append(b, streamNewlineBytes...) 60 } 61 return []byte("{\"error\":\"format error\"}" + streamNewline) 62 } 63 return []byte("Error: " + err.Error() + streamNewline) 64 } 65 66 func (sf *StreamFormatter) FormatProgress(id, action string, progress *jsonmessage.JSONProgress) []byte { 67 if progress == nil { 68 progress = &jsonmessage.JSONProgress{} 69 } 70 if sf.json { 71 b, err := json.Marshal(&jsonmessage.JSONMessage{ 72 Status: action, 73 ProgressMessage: progress.String(), 74 Progress: progress, 75 ID: id, 76 }) 77 if err != nil { 78 return nil 79 } 80 return b 81 } 82 endl := "\r" 83 if progress.String() == "" { 84 endl += "\n" 85 } 86 return []byte(action + " " + progress.String() + endl) 87 } 88 89 type StdoutFormater struct { 90 io.Writer 91 *StreamFormatter 92 } 93 94 func (sf *StdoutFormater) Write(buf []byte) (int, error) { 95 formattedBuf := sf.StreamFormatter.FormatStream(string(buf)) 96 n, err := sf.Writer.Write(formattedBuf) 97 if n != len(formattedBuf) { 98 return n, io.ErrShortWrite 99 } 100 return len(buf), err 101 } 102 103 type StderrFormater struct { 104 io.Writer 105 *StreamFormatter 106 } 107 108 func (sf *StderrFormater) Write(buf []byte) (int, error) { 109 formattedBuf := sf.StreamFormatter.FormatStream("\033[91m" + string(buf) + "\033[0m") 110 n, err := sf.Writer.Write(formattedBuf) 111 if n != len(formattedBuf) { 112 return n, io.ErrShortWrite 113 } 114 return len(buf), err 115 }