update go-plugin and hclog

This commit is contained in:
James Bardin 2018-10-02 16:03:07 -04:00 committed by Martin Atkins
parent 9f1098ac5f
commit 6f49a5d124
12 changed files with 306 additions and 65 deletions

7
go.mod
View File

@ -55,17 +55,18 @@ require (
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de
github.com/hashicorp/go-cleanhttp v0.0.0-20171130225243-06c9ea3a335b github.com/hashicorp/go-cleanhttp v0.0.0-20171130225243-06c9ea3a335b
github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86 github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86
github.com/hashicorp/go-hclog v0.0.0-20170716174523-b4e5765d1e5f github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f
github.com/hashicorp/go-immutable-radix v1.0.0 // indirect 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-msgpack v0.0.0-20150518234257-fa3f63826f7c // indirect
github.com/hashicorp/go-multierror v1.0.0 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-retryablehttp v0.0.0-20160930035102-6e85be8fee1d
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 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-safetemp v0.0.0-20180326211150-b1a1dbde6fdc // indirect
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 // indirect github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 // indirect
github.com/hashicorp/go-uuid v1.0.0 github.com/hashicorp/go-uuid v1.0.0
github.com/hashicorp/go-version v0.0.0-20180322230233-23480c066577 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/hcl v0.0.0-20170504190234-a4b07c25de5f
github.com/hashicorp/hcl2 v0.0.0-20180925175540-3f1c5474d4f7 github.com/hashicorp/hcl2 v0.0.0-20180925175540-3f1c5474d4f7
github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250 github.com/hashicorp/hil v0.0.0-20170627220502-fa9f258a9250

12
go.sum
View File

@ -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-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 h1:mv3oKLM8sTaxmU/PrT39T35HRnUfchK+vtzXw6Ci9lY=
github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86/go.mod h1:6rdJFnhkXnzGOJbvkrdv4t9nLwKcVA+tmbQeUlkIzrU= 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-20181001195459-61d530d6c27f h1:Yv9YzBlAETjy6AOX9eLBZ3nshNVRREgerT/3nvxlGho=
github.com/hashicorp/go-hclog v0.0.0-20170716174523-b4e5765d1e5f/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.0.0-20181001195459-61d530d6c27f/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v0.0.0-20180129170900-7f3cd4390caa h1:0nA8i+6Rwqaq9xlpmVxxTwk6rxiEhX+E6Wh4vPNHiS8=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= 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 h1:BTAbnbegUIMB6xmQCwWE8yRzbA4XSpnZY5hvRJC188I=
github.com/hashicorp/go-msgpack v0.0.0-20150518234257-fa3f63826f7c/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 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 h1:j30noezaCfvNLcdMYSvHLv81DxYRSt1grlpseG67vhU=
github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= 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 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= 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-20181002195811-1faddcf740b6 h1:czAJ5CXRPr+6vd6RGdJelApnxNbK3dAkakgBwLEWfrc=
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/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 h1:/T1aqTlRV/71ER/wHvhqTZaXGQW7XSO+F16mIIHw7zc=
github.com/hashicorp/go-retryablehttp v0.0.0-20160930035102-6e85be8fee1d/go.mod h1:fXcdFsQoipQa7mwORhKad5jmDCeSy/RCGzWA08PO0lM= 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= github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:9HVkPxOpo+yO93Ah4yrO67d/qh0fbLLWbKqhYjyHq9A=

1
vendor/github.com/hashicorp/go-hclog/.gitignore generated vendored Normal file
View File

@ -0,0 +1 @@
.idea*

View File

@ -10,8 +10,7 @@ interface for use in development and production environments.
It provides logging levels that provide decreased output based upon the It provides logging levels that provide decreased output based upon the
desired amount of output, unlike the standard library `log` package. desired amount of output, unlike the standard library `log` package.
It does not provide `Printf` style logging, only key/value logging that is It provides `Printf` style logging of values via `hclog.Fmt()`.
exposed as arguments to the logging functions for simplicity.
It provides a human readable output mode for use in development as well as It provides a human readable output mode for use in development as well as
JSON output mode for production. 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 This allows sub Loggers to be context specific without having to thread that
into all the callers. 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 ### 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 If you want to use the standard library's `log.Logger` interface you can wrap

7
vendor/github.com/hashicorp/go-hclog/go.mod generated vendored Normal file
View File

@ -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
)

6
vendor/github.com/hashicorp/go-hclog/go.sum generated vendored Normal file
View File

@ -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=

View File

@ -2,14 +2,19 @@ package hclog
import ( import (
"bufio" "bufio"
"bytes"
"encoding"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log" "log"
"os" "os"
"reflect"
"runtime" "runtime"
"sort"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"time" "time"
) )
@ -17,8 +22,8 @@ var (
_levelToBracket = map[Level]string{ _levelToBracket = map[Level]string{
Debug: "[DEBUG]", Debug: "[DEBUG]",
Trace: "[TRACE]", Trace: "[TRACE]",
Info: "[INFO ]", Info: "[INFO] ",
Warn: "[WARN ]", Warn: "[WARN] ",
Error: "[ERROR]", Error: "[ERROR]",
} }
) )
@ -39,28 +44,40 @@ func New(opts *LoggerOptions) Logger {
level = DefaultLevel level = DefaultLevel
} }
return &intLogger{ mtx := opts.Mutex
m: new(sync.Mutex), if mtx == nil {
json: opts.JSONFormat, mtx = new(sync.Mutex)
caller: opts.IncludeLocation,
name: opts.Name,
w: bufio.NewWriter(output),
level: level,
} }
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 // The internal logger implementation. Internal in that it is defined entirely
// by this package. // by this package.
type intLogger struct { type intLogger struct {
json bool json bool
caller bool caller bool
name string name string
timeFormat string
// this is a pointer so that it's shared by any derived loggers, since // this is a pointer so that it's shared by any derived loggers, since
// those derived loggers share the bufio.Writer as well. // those derived loggers share the bufio.Writer as well.
m *sync.Mutex m *sync.Mutex
w *bufio.Writer w *bufio.Writer
level Level level *int32
implied []interface{} 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 // 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. // or more severe that the threshold configured in the Logger.
func (z *intLogger) Log(level Level, msg string, args ...interface{}) { func (z *intLogger) Log(level Level, msg string, args ...interface{}) {
if level < z.level { if level < Level(atomic.LoadInt32(z.level)) {
return return
} }
@ -126,14 +143,14 @@ func trimCallerPath(path string) string {
// Non-JSON logging format function // Non-JSON logging format function
func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{}) { 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(' ') z.w.WriteByte(' ')
s, ok := _levelToBracket[level] s, ok := _levelToBracket[level]
if ok { if ok {
z.w.WriteString(s) z.w.WriteString(s)
} else { } else {
z.w.WriteString("[UNKN ]") z.w.WriteString("[?????]")
} }
if z.caller { if z.caller {
@ -174,7 +191,10 @@ func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{
FOR: FOR:
for i := 0; i < len(args); i = i + 2 { for i := 0; i < len(args); i = i + 2 {
var val string var (
val string
raw bool
)
switch st := args[i+1].(type) { switch st := args[i+1].(type) {
case string: case string:
@ -202,15 +222,23 @@ func (z *intLogger) log(t time.Time, level Level, msg string, args ...interface{
case CapturedStacktrace: case CapturedStacktrace:
stacktrace = st stacktrace = st
continue FOR continue FOR
case Format:
val = fmt.Sprintf(st[0].(string), st[1:]...)
default: 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.WriteByte(' ')
z.w.WriteString(args[i].(string)) z.w.WriteString(args[i].(string))
z.w.WriteByte('=') z.w.WriteByte('=')
if strings.ContainsAny(val, " \t\n\r") { if !raw && strings.ContainsAny(val, " \t\n\r") {
z.w.WriteByte('"') z.w.WriteByte('"')
z.w.WriteString(val) z.w.WriteString(val)
z.w.WriteByte('"') 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 // JSON logging function
func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interface{}) { func (z *intLogger) logJson(t time.Time, level Level, msg string, args ...interface{}) {
vals := map[string]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 args != nil && len(args) > 0 {
if len(args)%2 != 0 { if len(args)%2 != 0 {
cs, ok := args[len(args)-1].(CapturedStacktrace) 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... // without injecting into logs...
continue 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 // Indicate that the logger would emit TRACE level logs
func (z *intLogger) IsTrace() bool { 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 // Indicate that the logger would emit DEBUG level logs
func (z *intLogger) IsDebug() bool { 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 // Indicate that the logger would emit INFO level logs
func (z *intLogger) IsInfo() bool { 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 // Indicate that the logger would emit WARN level logs
func (z *intLogger) IsWarn() bool { 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 // Indicate that the logger would emit ERROR level logs
func (z *intLogger) IsError() bool { 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 // 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 // the given key/value pairs. This is used to create a context specific
// Logger. // Logger.
func (z *intLogger) With(args ...interface{}) Logger { func (z *intLogger) With(args ...interface{}) Logger {
if len(args)%2 != 0 {
panic("With() call requires paired arguments")
}
var nz intLogger = *z 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 return &nz
} }
@ -357,6 +471,8 @@ func (z *intLogger) Named(name string) Logger {
if nz.name != "" { if nz.name != "" {
nz.name = nz.name + "." + name nz.name = nz.name + "." + name
} else {
nz.name = name
} }
return &nz return &nz
@ -373,6 +489,12 @@ func (z *intLogger) ResetNamed(name string) Logger {
return &nz 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 // 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 // allows packages that expect to be using the standard library log to actually
// use this logger. // use this logger.

View File

@ -5,6 +5,7 @@ import (
"log" "log"
"os" "os"
"strings" "strings"
"sync"
) )
var ( var (
@ -12,7 +13,7 @@ var (
DefaultLevel = Info DefaultLevel = Info
) )
type Level int type Level int32
const ( const (
// This is a special level used to indicate that no level has been // This is a special level used to indicate that no level has been
@ -36,6 +37,18 @@ const (
Error Level = 5 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 // 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 // the level string is invalid. This facilitates setting the log level via
// config or environment variable by name in a predictable way. // config or environment variable by name in a predictable way.
@ -108,6 +121,10 @@ type Logger interface {
// the current name as well. // the current name as well.
ResetNamed(name string) Logger 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 // Return a value that conforms to the stdlib log.Logger interface
StandardLogger(opts *StandardLoggerOptions) *log.Logger StandardLogger(opts *StandardLoggerOptions) *log.Logger
} }
@ -127,12 +144,18 @@ type LoggerOptions struct {
// The threshold for the logger. Anything less severe is supressed // The threshold for the logger. Anything less severe is supressed
Level Level 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 Output io.Writer
// An optional mutex pointer in case Output is shared
Mutex *sync.Mutex
// Control if the output should be in JSON. // Control if the output should be in JSON.
JSONFormat bool JSONFormat bool
// Intclude file and line information in each log line // Include file and line information in each log line
IncludeLocation bool IncludeLocation bool
// The time format to use instead of the default
TimeFormat string
} }

47
vendor/github.com/hashicorp/go-hclog/nulllogger.go generated vendored Normal file
View File

@ -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)
}

View File

@ -358,11 +358,19 @@ func (c *Client) Kill() {
doneCh := c.doneLogging doneCh := c.doneLogging
c.l.Unlock() 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 { if process == nil {
return 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 // We need to check for address here. It is possible that the plugin
// started (process != nil) but has no address (addr == nil) if the // 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 // plugin failed at startup. If we do have an address, we need to close
@ -392,8 +400,12 @@ func (c *Client) Kill() {
if graceful { if graceful {
select { select {
case <-doneCh: 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 return
case <-time.After(250 * time.Millisecond): 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 // Goroutine to mark exit status
go func(pid int) { go func(pid int) {
// ensure the context is cancelled when we're done
defer ctxCancel()
// Wait for the process to die // Wait for the process to die
pidWait(pid) 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 the logging channel since that doesn't work on reattach
close(c.doneLogging) close(c.doneLogging)
// Cancel the context
ctxCancel()
}(p.Pid) }(p.Pid)
// Set the address and process // Set the address and process
@ -542,6 +553,7 @@ func (c *Client) Start() (addr net.Addr, err error) {
// Set the process // Set the process
c.process = cmd.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 // Make sure the command is properly cleaned up if there is an error
defer func() { defer func() {
@ -564,19 +576,28 @@ func (c *Client) Start() (addr net.Addr, err error) {
defer stderr_w.Close() defer stderr_w.Close()
defer stdout_w.Close() defer stdout_w.Close()
// ensure the context is cancelled when we're done
defer ctxCancel()
// Wait for the command to end. // 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 // 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() os.Stderr.Sync()
// Mark that we exited // Mark that we exited
close(exitCh) close(exitCh)
// Cancel the context, marking that we exited
ctxCancel()
// Set that we exited, which takes a lock // Set that we exited, which takes a lock
c.l.Lock() c.l.Lock()
defer c.l.Unlock() defer c.l.Unlock()

View File

@ -93,7 +93,7 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
protoVersion := int(opts.ProtocolVersion) protoVersion := int(opts.ProtocolVersion)
pluginSet := opts.Plugins pluginSet := opts.Plugins
protoType := ProtocolNetRPC 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 var clientVersions []int
if vs := os.Getenv("PLUGIN_PROTOCOL_VERSIONS"); vs != "" { if vs := os.Getenv("PLUGIN_PROTOCOL_VERSIONS"); vs != "" {
for _, s := range strings.Split(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. // compatible plugin version.
sort.Sort(sort.Reverse(sort.IntSlice(clientVersions))) sort.Sort(sort.Reverse(sort.IntSlice(clientVersions)))
@ -119,7 +119,7 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
opts.VersionedPlugins[protoVersion] = 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 var versions []int
for v := range opts.VersionedPlugins { for v := range opts.VersionedPlugins {
versions = append(versions, v) versions = append(versions, v)
@ -127,23 +127,26 @@ func protocolVersion(opts *ServeConfig) (int, Protocol, PluginSet) {
sort.Sort(sort.Reverse(sort.IntSlice(versions))) 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 { 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. // values even if they are not a protocol match.
protoVersion = version protoVersion = version
pluginSet = opts.VersionedPlugins[version] pluginSet = opts.VersionedPlugins[version]
// all plugins in a set must use the same transport, so check the first // If we have a configured gRPC server we should select a protocol
// for the protocol type if opts.GRPCServer != nil {
for _, p := range pluginSet { // All plugins in a set must use the same transport, so check the first
switch p.(type) { // for the protocol type
case GRPCPlugin: for _, p := range pluginSet {
protoType = ProtocolGRPC switch p.(type) {
default: case GRPCPlugin:
protoType = ProtocolNetRPC protoType = ProtocolGRPC
default:
protoType = ProtocolNetRPC
}
break
} }
break
} }
for _, clientVersion := range clientVersions { for _, clientVersion := range clientVersions {

4
vendor/modules.txt vendored
View File

@ -293,11 +293,11 @@ github.com/hashicorp/go-cleanhttp
# github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86 # github.com/hashicorp/go-getter v0.0.0-20180327010114-90bb99a48d86
github.com/hashicorp/go-getter github.com/hashicorp/go-getter
github.com/hashicorp/go-getter/helper/url 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-hclog
# github.com/hashicorp/go-multierror v1.0.0 # github.com/hashicorp/go-multierror v1.0.0
github.com/hashicorp/go-multierror 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-plugin
# github.com/hashicorp/go-retryablehttp v0.0.0-20160930035102-6e85be8fee1d # github.com/hashicorp/go-retryablehttp v0.0.0-20160930035102-6e85be8fee1d
github.com/hashicorp/go-retryablehttp github.com/hashicorp/go-retryablehttp