diff --git a/go.mod b/go.mod index 51a8438fb5..5ae46febcb 100644 --- a/go.mod +++ b/go.mod @@ -55,17 +55,18 @@ require ( github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de github.com/hashicorp/go-cleanhttp v0.0.0-20171130225243-06c9ea3a335b github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86 - github.com/hashicorp/go-hclog v0.0.0-20170716174523-b4e5765d1e5f - github.com/hashicorp/go-immutable-radix v1.0.0 // indirect + github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f + github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa // indirect github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c // indirect github.com/hashicorp/go-multierror v1.0.0 - github.com/hashicorp/go-plugin v0.0.0-20180814222501-a4620f9913d1 + github.com/hashicorp/go-plugin v0.0.0-20181002195811-1faddcf740b6 github.com/hashicorp/go-retryablehttp v0.0.0-20160930035102-6e85be8fee1d github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc // indirect github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 // indirect github.com/hashicorp/go-uuid v1.0.0 github.com/hashicorp/go-version v0.0.0-20180322230233-23480c066577 + github.com/hashicorp/golang-lru v0.5.0 // indirect github.com/hashicorp/hcl v0.0.0-20170504190234-a4b07c25de5f github.com/hashicorp/hcl2 v0.0.0-20180925175540-3f1c5474d4f7 github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250 diff --git a/go.sum b/go.sum index 1aa6f38b8d..c50d66f4f0 100644 --- a/go.sum +++ b/go.sum @@ -116,18 +116,18 @@ github.com/hashicorp/go-cleanhttp v0.0.0-20171130225243-06c9ea3a335b h1:xrvnoavY github.com/hashicorp/go-cleanhttp v0.0.0-20171130225243-06c9ea3a335b/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86 h1:mv3oKLM8sTaxmU/PrT39T35HRnUfchK+vtzXw6Ci9lY= github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86/go.mod h1:6rdJFnhkXnzGOJbvkrdv4t9nLwKcVA+tmbQeUlkIzrU= -github.com/hashicorp/go-hclog v0.0.0-20170716174523-b4e5765d1e5f h1:5onjUM14Pu2IrXp+iFQJYxswZoCn8PmSvVQ6IOic8uE= -github.com/hashicorp/go-hclog v0.0.0-20170716174523-b4e5765d1e5f/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= -github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= -github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f h1:Yv9YzBlAETjy6AOX9eLBZ3nshNVRREgerT/3nvxlGho= +github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa h1:0nA8i+6Rwqaq9xlpmVxxTwk6rxiEhX+E6Wh4vPNHiS8= +github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa/go.mod h1:6ij3Z20p+OhOkCSrA0gImAWoHYQRGbnlcuk6XYTiaRw= github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c h1:BTAbnbegUIMB6xmQCwWE8yRzbA4XSpnZY5hvRJC188I= github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0 h1:j30noezaCfvNLcdMYSvHLv81DxYRSt1grlpseG67vhU= github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-plugin v0.0.0-20180814222501-a4620f9913d1 h1:VOzBI0phmFk2VWekzswI3F7yEu6LPMKz/Bjd9wzRsI0= -github.com/hashicorp/go-plugin v0.0.0-20180814222501-a4620f9913d1/go.mod h1:JSqWYsict+jzcj0+xElxyrBQRPNoiWQuddnxArJ7XHQ= +github.com/hashicorp/go-plugin v0.0.0-20181002195811-1faddcf740b6 h1:czAJ5CXRPr+6vd6RGdJelApnxNbK3dAkakgBwLEWfrc= +github.com/hashicorp/go-plugin v0.0.0-20181002195811-1faddcf740b6/go.mod h1:JSqWYsict+jzcj0+xElxyrBQRPNoiWQuddnxArJ7XHQ= github.com/hashicorp/go-retryablehttp v0.0.0-20160930035102-6e85be8fee1d h1:/T1aqTlRV/71ER/wHvhqTZaXGQW7XSO+F16mIIHw7zc= github.com/hashicorp/go-retryablehttp v0.0.0-20160930035102-6e85be8fee1d/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM= github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:9HVkPxOpo+yO93Ah4yrO67d/qh0fbLLWbKqhYjyHq9A= diff --git a/vendor/github.com/hashicorp/go-hclog/.gitignore b/vendor/github.com/hashicorp/go-hclog/.gitignore new file mode 100644 index 0000000000..42cc4105ff --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/.gitignore @@ -0,0 +1 @@ +.idea* \ No newline at end of file diff --git a/vendor/github.com/hashicorp/go-hclog/README.md b/vendor/github.com/hashicorp/go-hclog/README.md index 614342b2d8..1153e28535 100644 --- a/vendor/github.com/hashicorp/go-hclog/README.md +++ b/vendor/github.com/hashicorp/go-hclog/README.md @@ -10,8 +10,7 @@ interface for use in development and production environments. It provides logging levels that provide decreased output based upon the desired amount of output, unlike the standard library `log` package. -It does not provide `Printf` style logging, only key/value logging that is -exposed as arguments to the logging functions for simplicity. +It provides `Printf` style logging of values via `hclog.Fmt()`. It provides a human readable output mode for use in development as well as JSON output mode for production. @@ -100,6 +99,17 @@ requestLogger.Info("we are transporting a request") This allows sub Loggers to be context specific without having to thread that into all the callers. +### Using `hclog.Fmt()` + +```go +var int totalBandwidth = 200 +appLogger.Info("total bandwidth exceeded", "bandwidth", hclog.Fmt("%d GB/s", totalBandwidth)) +``` + +```text +... [INFO ] my-app: total bandwidth exceeded: bandwidth="200 GB/s" +``` + ### Use this with code that uses the standard library logger If you want to use the standard library's `log.Logger` interface you can wrap diff --git a/vendor/github.com/hashicorp/go-hclog/go.mod b/vendor/github.com/hashicorp/go-hclog/go.mod new file mode 100644 index 0000000000..0d079a6544 --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/go.mod @@ -0,0 +1,7 @@ +module github.com/hashicorp/go-hclog + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/testify v1.2.2 +) diff --git a/vendor/github.com/hashicorp/go-hclog/go.sum b/vendor/github.com/hashicorp/go-hclog/go.sum new file mode 100644 index 0000000000..e03ee77d9e --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/go.sum @@ -0,0 +1,6 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= diff --git a/vendor/github.com/hashicorp/go-hclog/int.go b/vendor/github.com/hashicorp/go-hclog/int.go index 9f90c2877a..2aaa1f895d 100644 --- a/vendor/github.com/hashicorp/go-hclog/int.go +++ b/vendor/github.com/hashicorp/go-hclog/int.go @@ -2,14 +2,19 @@ package hclog import ( "bufio" + "bytes" + "encoding" "encoding/json" "fmt" "log" "os" + "reflect" "runtime" + "sort" "strconv" "strings" "sync" + "sync/atomic" "time" ) @@ -17,8 +22,8 @@ var ( _levelToBracket = map[Level]string{ Debug: "[DEBUG]", Trace: "[TRACE]", - Info: "[INFO ]", - Warn: "[WARN ]", + Info: "[INFO] ", + Warn: "[WARN] ", Error: "[ERROR]", } ) @@ -39,28 +44,40 @@ func New(opts *LoggerOptions) Logger { level = DefaultLevel } - return &intLogger{ - m: new(sync.Mutex), - json: opts.JSONFormat, - caller: opts.IncludeLocation, - name: opts.Name, - w: bufio.NewWriter(output), - level: level, + mtx := opts.Mutex + if mtx == nil { + mtx = new(sync.Mutex) } + + ret := &intLogger{ + m: mtx, + json: opts.JSONFormat, + caller: opts.IncludeLocation, + name: opts.Name, + timeFormat: TimeFormat, + w: bufio.NewWriter(output), + level: new(int32), + } + if opts.TimeFormat != "" { + ret.timeFormat = opts.TimeFormat + } + atomic.StoreInt32(ret.level, int32(level)) + return ret } // The internal logger implementation. Internal in that it is defined entirely // by this package. type intLogger struct { - json bool - caller bool - name string + json bool + caller bool + name string + timeFormat string // this is a pointer so that it's shared by any derived loggers, since // those derived loggers share the bufio.Writer as well. m *sync.Mutex w *bufio.Writer - level Level + level *int32 implied []interface{} } @@ -75,7 +92,7 @@ const TimeFormat = "2006-01-02T15:04:05.000Z0700" // Log a message and a set of key/value pairs if the given level is at // or more severe that the threshold configured in the Logger. func (z *intLogger) Log(level Level, msg string, args ...interface{}) { - if level < z.level { + if level < Level(atomic.LoadInt32(z.level)) { return } @@ -126,14 +143,14 @@ func trimCallerPath(path string) string { // Non-JSON logging format function func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{}) { - z.w.WriteString(t.Format(TimeFormat)) + z.w.WriteString(t.Format(z.timeFormat)) z.w.WriteByte(' ') s, ok := _levelToBracket[level] if ok { z.w.WriteString(s) } else { - z.w.WriteString("[UNKN ]") + z.w.WriteString("[?????]") } if z.caller { @@ -174,7 +191,10 @@ func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{ FOR: for i := 0; i < len(args); i = i + 2 { - var val string + var ( + val string + raw bool + ) switch st := args[i+1].(type) { case string: @@ -202,15 +222,23 @@ func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{ case CapturedStacktrace: stacktrace = st continue FOR + case Format: + val = fmt.Sprintf(st[0].(string), st[1:]...) default: - val = fmt.Sprintf("%v", st) + v := reflect.ValueOf(st) + if v.Kind() == reflect.Slice { + val = z.renderSlice(v) + raw = true + } else { + val = fmt.Sprintf("%v", st) + } } z.w.WriteByte(' ') z.w.WriteString(args[i].(string)) z.w.WriteByte('=') - if strings.ContainsAny(val, " \t\n\r") { + if !raw && strings.ContainsAny(val, " \t\n\r") { z.w.WriteByte('"') z.w.WriteString(val) z.w.WriteByte('"') @@ -227,6 +255,45 @@ func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{ } } +func (z *intLogger) renderSlice(v reflect.Value) string { + var buf bytes.Buffer + + buf.WriteRune('[') + + for i := 0; i < v.Len(); i++ { + if i > 0 { + buf.WriteString(", ") + } + + sv := v.Index(i) + + var val string + + switch sv.Kind() { + case reflect.String: + val = sv.String() + case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: + val = strconv.FormatInt(sv.Int(), 10) + case reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64: + val = strconv.FormatUint(sv.Uint(), 10) + default: + val = fmt.Sprintf("%v", sv.Interface()) + } + + if strings.ContainsAny(val, " \t\n\r") { + buf.WriteByte('"') + buf.WriteString(val) + buf.WriteByte('"') + } else { + buf.WriteString(val) + } + } + + buf.WriteRune(']') + + return buf.String() +} + // JSON logging function func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interface{}) { vals := map[string]interface{}{ @@ -262,6 +329,8 @@ func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interf } } + args = append(z.implied, args...) + if args != nil && len(args) > 0 { if len(args)%2 != 0 { cs, ok := args[len(args)-1].(CapturedStacktrace) @@ -279,7 +348,22 @@ func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interf // without injecting into logs... continue } - vals[args[i].(string)] = args[i+1] + val := args[i+1] + switch sv := val.(type) { + case error: + // Check if val is of type error. If error type doesn't + // implement json.Marshaler or encoding.TextMarshaler + // then set val to err.Error() so that it gets marshaled + switch sv.(type) { + case json.Marshaler, encoding.TextMarshaler: + default: + val = sv.Error() + } + case Format: + val = fmt.Sprintf(sv[0].(string), sv[1:]...) + } + + vals[args[i].(string)] = val } } @@ -316,36 +400,66 @@ func (z *intLogger) Error(msg string, args ...interface{}) { // Indicate that the logger would emit TRACE level logs func (z *intLogger) IsTrace() bool { - return z.level == Trace + return Level(atomic.LoadInt32(z.level)) == Trace } // Indicate that the logger would emit DEBUG level logs func (z *intLogger) IsDebug() bool { - return z.level <= Debug + return Level(atomic.LoadInt32(z.level)) <= Debug } // Indicate that the logger would emit INFO level logs func (z *intLogger) IsInfo() bool { - return z.level <= Info + return Level(atomic.LoadInt32(z.level)) <= Info } // Indicate that the logger would emit WARN level logs func (z *intLogger) IsWarn() bool { - return z.level <= Warn + return Level(atomic.LoadInt32(z.level)) <= Warn } // Indicate that the logger would emit ERROR level logs func (z *intLogger) IsError() bool { - return z.level <= Error + return Level(atomic.LoadInt32(z.level)) <= Error } // Return a sub-Logger for which every emitted log message will contain // the given key/value pairs. This is used to create a context specific // Logger. func (z *intLogger) With(args ...interface{}) Logger { + if len(args)%2 != 0 { + panic("With() call requires paired arguments") + } + var nz intLogger = *z - nz.implied = append(nz.implied, args...) + result := make(map[string]interface{}, len(z.implied)+len(args)) + keys := make([]string, 0, len(z.implied)+len(args)) + + // Read existing args, store map and key for consistent sorting + for i := 0; i < len(z.implied); i += 2 { + key := z.implied[i].(string) + keys = append(keys, key) + result[key] = z.implied[i+1] + } + // Read new args, store map and key for consistent sorting + for i := 0; i < len(args); i += 2 { + key := args[i].(string) + _, exists := result[key] + if !exists { + keys = append(keys, key) + } + result[key] = args[i+1] + } + + // Sort keys to be consistent + sort.Strings(keys) + + nz.implied = make([]interface{}, 0, len(z.implied)+len(args)) + for _, k := range keys { + nz.implied = append(nz.implied, k) + nz.implied = append(nz.implied, result[k]) + } return &nz } @@ -357,6 +471,8 @@ func (z *intLogger) Named(name string) Logger { if nz.name != "" { nz.name = nz.name + "." + name + } else { + nz.name = name } return &nz @@ -373,6 +489,12 @@ func (z *intLogger) ResetNamed(name string) Logger { return &nz } +// Update the logging level on-the-fly. This will affect all subloggers as +// well. +func (z *intLogger) SetLevel(level Level) { + atomic.StoreInt32(z.level, int32(level)) +} + // Create a *log.Logger that will send it's data through this Logger. This // allows packages that expect to be using the standard library log to actually // use this logger. diff --git a/vendor/github.com/hashicorp/go-hclog/log.go b/vendor/github.com/hashicorp/go-hclog/log.go index 6bb16ba75c..d98714e0a0 100644 --- a/vendor/github.com/hashicorp/go-hclog/log.go +++ b/vendor/github.com/hashicorp/go-hclog/log.go @@ -5,6 +5,7 @@ import ( "log" "os" "strings" + "sync" ) var ( @@ -12,7 +13,7 @@ var ( DefaultLevel = Info ) -type Level int +type Level int32 const ( // This is a special level used to indicate that no level has been @@ -36,6 +37,18 @@ const ( Error Level = 5 ) +// When processing a value of this type, the logger automatically treats the first +// argument as a Printf formatting string and passes the rest as the values to be +// formatted. For example: L.Info(Fmt{"%d beans/day", beans}). This is a simple +// convience type for when formatting is required. +type Format []interface{} + +// Fmt returns a Format type. This is a convience function for creating a Format +// type. +func Fmt(str string, args ...interface{}) Format { + return append(Format{str}, args...) +} + // LevelFromString returns a Level type for the named log level, or "NoLevel" if // the level string is invalid. This facilitates setting the log level via // config or environment variable by name in a predictable way. @@ -108,6 +121,10 @@ type Logger interface { // the current name as well. ResetNamed(name string) Logger + // Updates the level. This should affect all sub-loggers as well. If an + // implementation cannot update the level on the fly, it should no-op. + SetLevel(level Level) + // Return a value that conforms to the stdlib log.Logger interface StandardLogger(opts *StandardLoggerOptions) *log.Logger } @@ -127,12 +144,18 @@ type LoggerOptions struct { // The threshold for the logger. Anything less severe is supressed Level Level - // Where to write the logs to. Defaults to os.Stdout if nil + // Where to write the logs to. Defaults to os.Stderr if nil Output io.Writer + // An optional mutex pointer in case Output is shared + Mutex *sync.Mutex + // Control if the output should be in JSON. JSONFormat bool - // Intclude file and line information in each log line + // Include file and line information in each log line IncludeLocation bool + + // The time format to use instead of the default + TimeFormat string } diff --git a/vendor/github.com/hashicorp/go-hclog/nulllogger.go b/vendor/github.com/hashicorp/go-hclog/nulllogger.go new file mode 100644 index 0000000000..0942361a52 --- /dev/null +++ b/vendor/github.com/hashicorp/go-hclog/nulllogger.go @@ -0,0 +1,47 @@ +package hclog + +import ( + "io/ioutil" + "log" +) + +// NewNullLogger instantiates a Logger for which all calls +// will succeed without doing anything. +// Useful for testing purposes. +func NewNullLogger() Logger { + return &nullLogger{} +} + +type nullLogger struct{} + +func (l *nullLogger) Trace(msg string, args ...interface{}) {} + +func (l *nullLogger) Debug(msg string, args ...interface{}) {} + +func (l *nullLogger) Info(msg string, args ...interface{}) {} + +func (l *nullLogger) Warn(msg string, args ...interface{}) {} + +func (l *nullLogger) Error(msg string, args ...interface{}) {} + +func (l *nullLogger) IsTrace() bool { return false } + +func (l *nullLogger) IsDebug() bool { return false } + +func (l *nullLogger) IsInfo() bool { return false } + +func (l *nullLogger) IsWarn() bool { return false } + +func (l *nullLogger) IsError() bool { return false } + +func (l *nullLogger) With(args ...interface{}) Logger { return l } + +func (l *nullLogger) Named(name string) Logger { return l } + +func (l *nullLogger) ResetNamed(name string) Logger { return l } + +func (l *nullLogger) SetLevel(level Level) {} + +func (l *nullLogger) StandardLogger(opts *StandardLoggerOptions) *log.Logger { + return log.New(ioutil.Discard, "", log.LstdFlags) +} diff --git a/vendor/github.com/hashicorp/go-plugin/client.go b/vendor/github.com/hashicorp/go-plugin/client.go index 1528305d9e..bfab795acf 100644 --- a/vendor/github.com/hashicorp/go-plugin/client.go +++ b/vendor/github.com/hashicorp/go-plugin/client.go @@ -358,11 +358,19 @@ func (c *Client) Kill() { doneCh := c.doneLogging c.l.Unlock() - // If there is no process, we never started anything. Nothing to kill. + // If there is no process, there is nothing to kill. if process == nil { return } + defer func() { + // Make sure there is no reference to the old process after it has been + // killed. + c.l.Lock() + defer c.l.Unlock() + c.process = nil + }() + // We need to check for address here. It is possible that the plugin // started (process != nil) but has no address (addr == nil) if the // plugin failed at startup. If we do have an address, we need to close @@ -392,8 +400,12 @@ func (c *Client) Kill() { if graceful { select { case <-doneCh: + // FIXME: this is never reached under normal circumstances, because + // the plugin process is never signaled to exit. We can reach this + // if the child process exited abnormally before the Kill call. return case <-time.After(250 * time.Millisecond): + c.logger.Warn("plugin failed to exit gracefully") } } @@ -460,6 +472,8 @@ func (c *Client) Start() (addr net.Addr, err error) { // Goroutine to mark exit status go func(pid int) { + // ensure the context is cancelled when we're done + defer ctxCancel() // Wait for the process to die pidWait(pid) @@ -473,9 +487,6 @@ func (c *Client) Start() (addr net.Addr, err error) { // Close the logging channel since that doesn't work on reattach close(c.doneLogging) - - // Cancel the context - ctxCancel() }(p.Pid) // Set the address and process @@ -542,6 +553,7 @@ func (c *Client) Start() (addr net.Addr, err error) { // Set the process c.process = cmd.Process + c.logger.Debug("plugin started", "path", cmd.Path, "pid", c.process.Pid) // Make sure the command is properly cleaned up if there is an error defer func() { @@ -564,19 +576,28 @@ func (c *Client) Start() (addr net.Addr, err error) { defer stderr_w.Close() defer stdout_w.Close() + // ensure the context is cancelled when we're done + defer ctxCancel() + // Wait for the command to end. - cmd.Wait() + err := cmd.Wait() + + debugMsgArgs := []interface{}{ + "path", cmd.Path, + "pid", c.process.Pid, + } + if err != nil { + debugMsgArgs = append(debugMsgArgs, + []interface{}{"error", err.Error()}...) + } // Log and make sure to flush the logs write away - c.logger.Debug("plugin process exited", "path", cmd.Path) + c.logger.Debug("plugin process exited", debugMsgArgs...) os.Stderr.Sync() // Mark that we exited close(exitCh) - // Cancel the context, marking that we exited - ctxCancel() - // Set that we exited, which takes a lock c.l.Lock() defer c.l.Unlock() diff --git a/vendor/github.com/hashicorp/go-plugin/server.go b/vendor/github.com/hashicorp/go-plugin/server.go index 6de90485f6..c278e53a2f 100644 --- a/vendor/github.com/hashicorp/go-plugin/server.go +++ b/vendor/github.com/hashicorp/go-plugin/server.go @@ -93,7 +93,7 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) { protoVersion := int(opts.ProtocolVersion) pluginSet := opts.Plugins protoType := ProtocolNetRPC - // check if the client sent a list of acceptable versions + // Check if the client sent a list of acceptable versions var clientVersions []int if vs := os.Getenv("PLUGIN_PROTOCOL_VERSIONS"); vs != "" { for _, s := range strings.Split(vs, ",") { @@ -106,7 +106,7 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) { } } - // we want to iterate in reverse order, to ensure we match the newest + // We want to iterate in reverse order, to ensure we match the newest // compatible plugin version. sort.Sort(sort.Reverse(sort.IntSlice(clientVersions))) @@ -119,7 +119,7 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) { opts.VersionedPlugins[protoVersion] = pluginSet } - // sort the version to make sure we match the latest first + // Sort the version to make sure we match the latest first var versions []int for v := range opts.VersionedPlugins { versions = append(versions, v) @@ -127,23 +127,26 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) { sort.Sort(sort.Reverse(sort.IntSlice(versions))) - // see if we have multiple versions of Plugins to choose from + // See if we have multiple versions of Plugins to choose from for _, version := range versions { - // record each version, since we guarantee that this returns valid + // Record each version, since we guarantee that this returns valid // values even if they are not a protocol match. protoVersion = version pluginSet = opts.VersionedPlugins[version] - // all plugins in a set must use the same transport, so check the first - // for the protocol type - for _, p := range pluginSet { - switch p.(type) { - case GRPCPlugin: - protoType = ProtocolGRPC - default: - protoType = ProtocolNetRPC + // If we have a configured gRPC server we should select a protocol + if opts.GRPCServer != nil { + // All plugins in a set must use the same transport, so check the first + // for the protocol type + for _, p := range pluginSet { + switch p.(type) { + case GRPCPlugin: + protoType = ProtocolGRPC + default: + protoType = ProtocolNetRPC + } + break } - break } for _, clientVersion := range clientVersions { diff --git a/vendor/modules.txt b/vendor/modules.txt index 3f4a71d3a3..204fe3a4bd 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -293,11 +293,11 @@ github.com/hashicorp/go-cleanhttp # github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86 github.com/hashicorp/go-getter github.com/hashicorp/go-getter/helper/url -# github.com/hashicorp/go-hclog v0.0.0-20170716174523-b4e5765d1e5f +# github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f github.com/hashicorp/go-hclog # github.com/hashicorp/go-multierror v1.0.0 github.com/hashicorp/go-multierror -# github.com/hashicorp/go-plugin v0.0.0-20180814222501-a4620f9913d1 +# github.com/hashicorp/go-plugin v0.0.0-20181002195811-1faddcf740b6 github.com/hashicorp/go-plugin # github.com/hashicorp/go-retryablehttp v0.0.0-20160930035102-6e85be8fee1d github.com/hashicorp/go-retryablehttp