diff --git a/api/go.sum b/api/go.sum index 56fb281105..172833fa1e 100644 --- a/api/go.sum +++ b/api/go.sum @@ -2,9 +2,11 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= @@ -65,6 +67,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -82,6 +85,7 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= diff --git a/api/sys_audit.go b/api/sys_audit.go index 2448c0367c..5fa6f3585d 100644 --- a/api/sys_audit.go +++ b/api/sys_audit.go @@ -116,7 +116,7 @@ func (c *Sys) DisableAudit(path string) error { return err } -// Structures for the requests/resposne are all down here. They aren't +// Structures for the requests/response are all down here. They aren't // individually documented because the map almost directly to the raw HTTP API // documentation. Please refer to that documentation for more details. diff --git a/api/sys_monitor.go b/api/sys_monitor.go new file mode 100644 index 0000000000..ec27f22855 --- /dev/null +++ b/api/sys_monitor.go @@ -0,0 +1,64 @@ +package api + +import ( + "bufio" + "context" + "fmt" +) + +// Monitor returns a channel that outputs strings containing the log messages +// coming from the server. +func (c *Sys) Monitor(ctx context.Context, logLevel string) (chan string, error) { + r := c.c.NewRequest("GET", "/v1/sys/monitor") + + if logLevel == "" { + r.Params.Add("log_level", "info") + } else { + r.Params.Add("log_level", logLevel) + } + + resp, err := c.c.RawRequestWithContext(ctx, r) + if err != nil { + return nil, err + } + + logCh := make(chan string, 64) + + go func() { + scanner := bufio.NewScanner(resp.Body) + droppedCount := 0 + + defer close(logCh) + defer resp.Body.Close() + + for { + if ctx.Err() != nil { + return + } + + if !scanner.Scan() { + return + } + + logMessage := scanner.Text() + + if droppedCount > 0 { + select { + case logCh <- fmt.Sprintf("Monitor dropped %d logs during monitor request\n", droppedCount): + droppedCount = 0 + default: + droppedCount++ + continue + } + } + + select { + case logCh <- logMessage: + default: + droppedCount++ + } + } + }() + + return logCh, nil +} diff --git a/builtin/credential/okta/path_config.go b/builtin/credential/okta/path_config.go index 538d4b537f..0f2f7a52df 100644 --- a/builtin/credential/okta/path_config.go +++ b/builtin/credential/okta/path_config.go @@ -8,8 +8,8 @@ import ( "strings" "time" - "github.com/hashicorp/go-cleanhttp" oktaold "github.com/chrismalek/oktasdk-go/okta" + "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/vault/sdk/framework" "github.com/hashicorp/vault/sdk/helper/tokenutil" "github.com/hashicorp/vault/sdk/logical" diff --git a/command/agent/cf_end_to_end_test.go b/command/agent/cf_end_to_end_test.go index 865b62c1e7..411ca05508 100644 --- a/command/agent/cf_end_to_end_test.go +++ b/command/agent/cf_end_to_end_test.go @@ -8,7 +8,6 @@ import ( "time" hclog "github.com/hashicorp/go-hclog" - log "github.com/hashicorp/go-hclog" credCF "github.com/hashicorp/vault-plugin-auth-cf" "github.com/hashicorp/vault-plugin-auth-cf/testing/certificates" cfAPI "github.com/hashicorp/vault-plugin-auth-cf/testing/cf" @@ -29,7 +28,7 @@ func TestCFEndToEnd(t *testing.T) { coreConfig := &vault.CoreConfig{ DisableMlock: true, DisableCache: true, - Logger: log.NewNullLogger(), + Logger: hclog.NewNullLogger(), CredentialBackends: map[string]logical.Factory{ "cf": credCF.Factory, }, diff --git a/command/command_test.go b/command/command_test.go index dec1b0ad01..32426fd83a 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/vault/builtin/logical/ssh" "github.com/hashicorp/vault/builtin/logical/transit" "github.com/hashicorp/vault/helper/builtinplugins" + "github.com/hashicorp/vault/sdk/helper/logging" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/physical/inmem" "github.com/hashicorp/vault/vault" @@ -84,11 +85,16 @@ func testVaultServerAllBackends(tb testing.TB) (*api.Client, func()) { // API client, list of unseal keys (as strings), and a closer function. func testVaultServerUnseal(tb testing.TB) (*api.Client, []string, func()) { tb.Helper() + logger := log.NewInterceptLogger(&log.LoggerOptions{ + Output: log.DefaultOutput, + Level: log.Debug, + JSONFormat: logging.ParseEnvLogFormat() == logging.JSONFormat, + }) return testVaultServerCoreConfig(tb, &vault.CoreConfig{ DisableMlock: true, DisableCache: true, - Logger: defaultVaultLogger, + Logger: logger, CredentialBackends: defaultVaultCredentialBackends, AuditBackends: defaultVaultAuditBackends, LogicalBackends: defaultVaultLogicalBackends, diff --git a/command/commands.go b/command/commands.go index 1f1d8ae913..a679303fa0 100644 --- a/command/commands.go +++ b/command/commands.go @@ -667,6 +667,12 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) { BaseCommand: getBaseCommand(), }, nil }, + "monitor": func() (cli.Command, error) { + return &MonitorCommand{ + BaseCommand: getBaseCommand(), + ShutdownCh: MakeShutdownCh(), + }, nil + }, } } diff --git a/command/monitor.go b/command/monitor.go new file mode 100644 index 0000000000..d78b1ffbec --- /dev/null +++ b/command/monitor.go @@ -0,0 +1,118 @@ +package command + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/vault/sdk/helper/strutil" + "github.com/mitchellh/cli" + "github.com/posener/complete" +) + +var _ cli.Command = (*MonitorCommand)(nil) +var _ cli.CommandAutocomplete = (*MonitorCommand)(nil) + +type MonitorCommand struct { + *BaseCommand + + logLevel string + + // ShutdownCh is used to capture interrupt signal and end streaming + ShutdownCh chan struct{} +} + +func (c *MonitorCommand) Synopsis() string { + return "Stream log messages from a Vault server" +} + +func (c *MonitorCommand) Help() string { + helpText := ` +Usage: vault monitor [options] + + Stream log messages of a Vault server. The monitor command lets you listen + for log levels that may be filtered out of the server logs. For example, + the server may be logging at the INFO level, but with the monitor command + you can set -log-level=DEBUG. + +` + c.Flags().Help() + + return strings.TrimSpace(helpText) +} + +func (c *MonitorCommand) Flags() *FlagSets { + set := c.flagSet(FlagSetHTTP) + + f := set.NewFlagSet("Monitor Options") + f.StringVar(&StringVar{ + Name: "log-level", + Target: &c.logLevel, + Default: "info", + Completion: complete.PredictSet("trace", "debug", "info", "warn", "error"), + Usage: "If passed, the log level to monitor logs. Supported values" + + "(in order of detail) are \"trace\", \"debug\", \"info\", \"warn\"" + + " and \"error\". These are not case sensitive.", + }) + + return set +} + +func (c *MonitorCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + +func (c *MonitorCommand) AutocompleteFlags() complete.Flags { + return c.Flags().Completions() +} + +func (c *MonitorCommand) Run(args []string) int { + f := c.Flags() + + if err := f.Parse(args); err != nil { + c.UI.Error(err.Error()) + return 1 + } + + parsedArgs := f.Args() + if len(parsedArgs) > 0 { + c.UI.Error(fmt.Sprintf("Too many arguments (expected 0, got %d)", len(parsedArgs))) + return 1 + } + + c.logLevel = strings.ToLower(c.logLevel) + validLevels := []string{"trace", "debug", "info", "warn", "error"} + if !strutil.StrListContains(validLevels, c.logLevel) { + c.UI.Error(fmt.Sprintf("%s is an unknown log level. Valid log levels are: %s", c.logLevel, validLevels)) + return 1 + } + + client, err := c.Client() + if err != nil { + c.UI.Error(err.Error()) + return 2 + } + + // Remove the default 60 second timeout so we can stream indefinitely + client.SetClientTimeout(0) + + var logCh chan string + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + logCh, err = client.Sys().Monitor(ctx, c.logLevel) + if err != nil { + c.UI.Error(fmt.Sprintf("Error starting monitor: %s", err)) + return 1 + } + + for { + select { + case log, ok := <-logCh: + if !ok { + return 0 + } + c.UI.Info(log) + case <-c.ShutdownCh: + return 0 + } + } +} diff --git a/command/monitor_test.go b/command/monitor_test.go new file mode 100644 index 0000000000..9f4bde934a --- /dev/null +++ b/command/monitor_test.go @@ -0,0 +1,99 @@ +package command + +import ( + "strings" + "sync/atomic" + "testing" + "time" + + "github.com/hashicorp/vault/helper/testhelpers" + "github.com/mitchellh/cli" +) + +func testMonitorCommand(tb testing.TB) (*cli.MockUi, *MonitorCommand) { + tb.Helper() + + ui := cli.NewMockUi() + return ui, &MonitorCommand{ + BaseCommand: &BaseCommand{ + UI: ui, + }, + } +} + +func TestMonitorCommand_Run(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + args []string + out string + code int64 + }{ + { + "valid", + []string{ + "-log-level=debug", + }, + "", + 0, + }, + { + "too_many_args", + []string{ + "-log-level=debug", + "foo", + }, + "Too many arguments", + 1, + }, + { + "unknown_log_level", + []string{ + "-log-level=haha", + }, + "haha is an unknown log level", + 1, + }, + } + + for _, tc := range cases { + tc := tc + + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + client, closer := testVaultServer(t) + defer closer() + + var code int64 + shutdownCh := make(chan struct{}) + + ui, cmd := testMonitorCommand(t) + cmd.client = client + cmd.ShutdownCh = shutdownCh + + stopCh := testhelpers.GenerateDebugLogs(t, client) + + go func() { + atomic.StoreInt64(&code, int64(cmd.Run(tc.args))) + }() + + select { + case <-time.After(3 * time.Second): + stopCh <- struct{}{} + close(shutdownCh) + } + + if atomic.LoadInt64(&code) != tc.code { + t.Errorf("expected %d to be %d", code, tc.code) + } + + combined := ui.OutputWriter.String() + ui.ErrorWriter.String() + if !strings.Contains(combined, tc.out) { + t.Fatalf("expected %q to contain %q", combined, tc.out) + } + + <-stopCh + }) + } +} diff --git a/command/server.go b/command/server.go index 0cf8660536..cc9de5a4da 100644 --- a/command/server.go +++ b/command/server.go @@ -412,7 +412,7 @@ func (c *ServerCommand) runRecoveryMode() int { return 1 } - c.logger = log.New(&log.LoggerOptions{ + c.logger = log.NewInterceptLogger(&log.LoggerOptions{ Output: c.gatedWriter, Level: level, // Note that if logFormat is either unspecified or standard, then @@ -868,14 +868,16 @@ func (c *ServerCommand) Run(args []string) int { return 1 } + config.LogFormat = logFormat.String() + if c.flagDevThreeNode || c.flagDevFourCluster { - c.logger = log.New(&log.LoggerOptions{ + c.logger = log.NewInterceptLogger(&log.LoggerOptions{ Mutex: &sync.Mutex{}, Output: c.gatedWriter, Level: log.Trace, }) } else { - c.logger = log.New(&log.LoggerOptions{ + c.logger = log.NewInterceptLogger(&log.LoggerOptions{ Output: c.gatedWriter, Level: level, // Note that if logFormat is either unspecified or standard, then diff --git a/go.mod b/go.mod index 0b3808ab19..d3dd1e55a3 100644 --- a/go.mod +++ b/go.mod @@ -101,7 +101,7 @@ require ( github.com/kr/pretty v0.2.0 github.com/kr/text v0.1.0 github.com/lib/pq v1.2.0 - github.com/mattn/go-colorable v0.1.4 + github.com/mattn/go-colorable v0.1.6 github.com/mholt/archiver v3.1.1+incompatible github.com/michaelklishin/rabbit-hole v0.0.0-20191008194146-93d9988f0cd5 github.com/mitchellh/cli v1.0.0 diff --git a/go.sum b/go.sum index e8717a8120..0fdc3c252b 100644 --- a/go.sum +++ b/go.sum @@ -191,9 +191,12 @@ github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHo github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0 h1:XJIw/+VlJ+87J+doOxznsAWIdmWuViOVhkQamW5YV28= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= @@ -234,7 +237,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= @@ -294,6 +296,7 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -406,6 +409,7 @@ github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrj github.com/hashicorp/go-hclog v0.9.1/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.13.0 h1:Do32YnDMnq7v7FU50AgH+1ExKCOkl9HBxvSI1JWr+rA= github.com/hashicorp/go-hclog v0.13.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -494,8 +498,6 @@ github.com/hashicorp/vault-plugin-database-mongodbatlas v0.1.1 h1:fA6cFH8lIPH2M4 github.com/hashicorp/vault-plugin-database-mongodbatlas v0.1.1/go.mod h1:MP3kfr0N+7miOTZFwKv952b9VkXM4S2Q6YtQCiNKWq8= github.com/hashicorp/vault-plugin-secrets-ad v0.6.4-beta1.0.20200518124111-3dceeb3ce90e h1:0GK1BNBfglD2sydZ4XXMjJElhY8bC2TDdc0vk1Q9zbA= github.com/hashicorp/vault-plugin-secrets-ad v0.6.4-beta1.0.20200518124111-3dceeb3ce90e/go.mod h1:SCsKcChP8yrtOHXOeTD7oRk0oflj3IxA9y9zTOGtQ8s= -github.com/hashicorp/vault-plugin-secrets-ad v0.6.5 h1:wrHzXSD6qmKvkuHaQn+BNj89+HGhMNchxAckGnd7YTc= -github.com/hashicorp/vault-plugin-secrets-ad v0.6.5/go.mod h1:kk98nB+cwDbt3I7UGQq3ota7+eHZrGSTQZfSRGpluvA= github.com/hashicorp/vault-plugin-secrets-alicloud v0.5.5 h1:BOOtSls+BQ1EtPmpE9LoqZztsEZ1fRWVSkHWtRIrCB4= github.com/hashicorp/vault-plugin-secrets-alicloud v0.5.5/go.mod h1:gAoReoUpBHaBwkxQqTK7FY8nQC0MuaZHLiW5WOSny5g= github.com/hashicorp/vault-plugin-secrets-azure v0.5.6 h1:4PgQ5rCT29wW5PMyebEhPkEYuR5s+SnInuZz3x2cP50= @@ -589,12 +591,12 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 h1:YFh+sjyJTMQSYjKwM4dFKhJPJC/wfo98tPUc17HdoYw= github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= @@ -978,15 +980,20 @@ golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/helper/monitor/monitor.go b/helper/monitor/monitor.go new file mode 100644 index 0000000000..490e2fa08b --- /dev/null +++ b/helper/monitor/monitor.go @@ -0,0 +1,166 @@ +package monitor + +import ( + "fmt" + "time" + + log "github.com/hashicorp/go-hclog" + "go.uber.org/atomic" +) + +// Monitor provides a mechanism to stream logs using go-hclog +// InterceptLogger and SinkAdapter. It allows streaming of logs +// at a different log level than what is set on the logger. +type Monitor interface { + // Start returns a channel of log messages which are sent + // every time a log message occurs + Start() <-chan []byte + + // Stop de-registers the sink from the InterceptLogger + // and closes the log channels + Stop() +} + +// monitor implements the Monitor interface. Note that this +// struct is not threadsafe. +type monitor struct { + sink log.SinkAdapter + + // logger is the logger we will be monitoring + logger log.InterceptLogger + + // logCh is a buffered chan where we send logs when streaming + logCh chan []byte + + // doneCh coordinates the shutdown of logCh + doneCh chan struct{} + + // droppedCount is the current count of messages + // that were dropped from the logCh buffer. + droppedCount *atomic.Uint32 + bufSize int + + // dropCheckInterval is the amount of time we should + // wait to check for dropped messages. Defaults + // to 3 seconds + dropCheckInterval time.Duration + + // started is whether the monitor has been started or not. + // This is to ensure that we don't start it again until + // it has been shut down. + started *atomic.Bool +} + +// NewMonitor creates a new Monitor. Start must be called in order to actually start +// streaming logs. buf is the buffer size of the channel that sends log messages. +func NewMonitor(buf int, logger log.InterceptLogger, opts *log.LoggerOptions) (Monitor, error) { + return newMonitor(buf, logger, opts) +} + +func newMonitor(buf int, logger log.InterceptLogger, opts *log.LoggerOptions) (*monitor, error) { + if buf <= 0 { + return nil, fmt.Errorf("buf must be greater than zero") + } + + sw := &monitor{ + logger: logger, + logCh: make(chan []byte, buf), + doneCh: make(chan struct{}), + bufSize: buf, + dropCheckInterval: 3 * time.Second, + droppedCount: atomic.NewUint32(0), + started: atomic.NewBool(false), + } + + opts.Output = sw + sink := log.NewSinkAdapter(opts) + sw.sink = sink + + return sw, nil +} + +// Stop deregisters the sink and stops the monitoring process +func (d *monitor) Stop() { + d.logger.DeregisterSink(d.sink) + close(d.doneCh) + d.started.Store(false) +} + +// Start registers a sink on the monitor's logger and starts sending +// received log messages over the returned channel. +func (d *monitor) Start() <-chan []byte { + // Check to see if this has already been started. If not, flag + // it and proceed. If so, bail out early. + if !d.started.CAS(false, true) { + return nil + } + + // register our sink with the logger + d.logger.RegisterSink(d.sink) + + streamCh := make(chan []byte, d.bufSize) + + // Run a go routine that listens for streamed + // log messages and sends them to streamCh. + // + // It also periodically checks for dropped + // messages and makes room on the logCh to add + // a dropped message count warning + go func() { + defer close(streamCh) + + ticker := time.NewTicker(d.dropCheckInterval) + defer ticker.Stop() + + var logMessage []byte + for { + logMessage = nil + + select { + case <-ticker.C: + // Check if there have been any dropped messages. + dc := d.droppedCount.Load() + + if dc > 0 { + logMessage = []byte(fmt.Sprintf("Monitor dropped %d logs during monitor request\n", dc)) + d.droppedCount.Swap(0) + } + case logMessage = <-d.logCh: + case <-d.doneCh: + return + } + + if len(logMessage) > 0 { + select { + case <-d.doneCh: + return + case streamCh <- logMessage: + } + } + } + }() + + return streamCh +} + +// Write attempts to send latest log to logCh +// it drops the log if channel is unavailable to receive +func (d *monitor) Write(p []byte) (n int, err error) { + // ensure logCh is still open + select { + case <-d.doneCh: + return + default: + } + + bytes := make([]byte, len(p)) + copy(bytes, p) + + select { + case d.logCh <- bytes: + default: + d.droppedCount.Add(1) + } + + return len(p), nil +} diff --git a/helper/monitor/monitor_test.go b/helper/monitor/monitor_test.go new file mode 100644 index 0000000000..7ae7a0fe8d --- /dev/null +++ b/helper/monitor/monitor_test.go @@ -0,0 +1,96 @@ +package monitor + +import ( + "fmt" + "strings" + "testing" + "time" + + log "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/require" +) + +func TestMonitor_Start(t *testing.T) { + t.Parallel() + + logger := log.NewInterceptLogger(&log.LoggerOptions{ + Level: log.Error, + }) + + m, _ := NewMonitor(512, logger, &log.LoggerOptions{ + Level: log.Debug, + }) + + logCh := m.Start() + defer m.Stop() + + go func() { + logger.Debug("test log") + time.Sleep(10 * time.Millisecond) + }() + + select { + case l := <-logCh: + require.Contains(t, string(l), "[DEBUG] test log") + return + case <-time.After(5 * time.Second): + t.Fatal("Expected to receive from log channel") + } +} + +func TestMonitor_Start_Unbuffered(t *testing.T) { + t.Parallel() + + logger := log.NewInterceptLogger(&log.LoggerOptions{ + Level: log.Error, + }) + + _, err := NewMonitor(0, logger, &log.LoggerOptions{ + Level: log.Debug, + }) + + if err == nil { + t.Fatal("expected to get an error, but didn't") + } else { + if !strings.Contains(err.Error(), "greater than zero") { + t.Fatal("expected an error about buf being greater than zero") + } + } +} + +// Ensure number of dropped messages are logged +func TestMonitor_DroppedMessages(t *testing.T) { + t.Parallel() + + logger := log.NewInterceptLogger(&log.LoggerOptions{ + Level: log.Warn, + }) + + m, _ := newMonitor(5, logger, &log.LoggerOptions{ + Level: log.Debug, + }) + m.dropCheckInterval = 5 * time.Millisecond + + logCh := m.Start() + defer m.Stop() + + for i := 0; i <= 100; i++ { + logger.Debug(fmt.Sprintf("test message %d", i)) + } + + passed := make(chan struct{}) + go func() { + for recv := range logCh { + if strings.Contains(string(recv), "Monitor dropped") { + close(passed) + return + } + } + }() + + select { + case <-passed: + case <-time.After(2 * time.Second): + require.Fail(t, "expected to see warn dropped messages") + } +} diff --git a/helper/testhelpers/testhelpers.go b/helper/testhelpers/testhelpers.go index 0939481f1b..25b2be8f03 100644 --- a/helper/testhelpers/testhelpers.go +++ b/helper/testhelpers/testhelpers.go @@ -493,3 +493,39 @@ func SetRaftAddressProviders(t testing.T, cluster *vault.TestCluster, provider r core.UnderlyingRawStorage.(*raft.RaftBackend).SetServerAddressProvider(provider) } } + +func GenerateDebugLogs(t testing.T, client *api.Client) chan struct{} { + t.Helper() + + stopCh := make(chan struct{}) + ticker := time.NewTicker(time.Second) + var err error + + go func() { + for { + select { + case <-stopCh: + ticker.Stop() + stopCh <- struct{}{} + return + case <-ticker.C: + err = client.Sys().Mount("foo", &api.MountInput{ + Type: "kv", + Options: map[string]string{ + "version": "1", + }, + }) + if err != nil { + t.Fatal(err) + } + + err = client.Sys().Unmount("foo") + if err != nil { + t.Fatal(err) + } + } + } + }() + + return stopCh +} diff --git a/http/handler.go b/http/handler.go index 62517eb457..0549d21d87 100644 --- a/http/handler.go +++ b/http/handler.go @@ -133,6 +133,7 @@ func Handler(props *vault.HandlerProperties) http.Handler { mux.Handle("/v1/sys/unseal", handleSysUnseal(core)) mux.Handle("/v1/sys/leader", handleSysLeader(core)) mux.Handle("/v1/sys/health", handleSysHealth(core)) + mux.Handle("/v1/sys/monitor", handleLogicalNoForward(core)) mux.Handle("/v1/sys/generate-root/attempt", handleRequestForwarding(core, handleAuditNonLogical(core, handleSysGenerateRootAttempt(core, vault.GenerateStandardRootTokenStrategy)))) mux.Handle("/v1/sys/generate-root/update", handleRequestForwarding(core, @@ -274,8 +275,12 @@ func wrapGenericHandler(core *vault.Core, h http.Handler, props *vault.HandlerPr // Start with the request context ctx := r.Context() var cancelFunc context.CancelFunc - // Add our timeout - ctx, cancelFunc = context.WithTimeout(ctx, maxRequestDuration) + // Add our timeout, but not for the monitor endpoint, as it's streaming + if strings.HasSuffix(r.URL.Path, "sys/monitor") { + ctx, cancelFunc = context.WithCancel(ctx) + } else { + ctx, cancelFunc = context.WithTimeout(ctx, maxRequestDuration) + } // Add a size limiter if desired if maxRequestSize > 0 { ctx = context.WithValue(ctx, "max_request_size", maxRequestSize) diff --git a/http/logical.go b/http/logical.go index 57ec03629b..2a7e0c9a49 100644 --- a/http/logical.go +++ b/http/logical.go @@ -86,6 +86,9 @@ func buildLogicalRequestNoAuth(perfStandby bool, w http.ResponseWriter, r *http. responseWriter = w case path == "sys/storage/raft/snapshot": responseWriter = w + case path == "sys/monitor": + passHTTPReq = true + responseWriter = w } case "POST", "PUT": @@ -142,13 +145,13 @@ func buildLogicalRequestNoAuth(perfStandby bool, w http.ResponseWriter, r *http. return nil, nil, http.StatusMethodNotAllowed, nil } - request_id, err := uuid.GenerateUUID() + requestId, err := uuid.GenerateUUID() if err != nil { return nil, nil, http.StatusBadRequest, errwrap.Wrapf("failed to generate identifier for the request: {{err}}", err) } req := &logical.Request{ - ID: request_id, + ID: requestId, Operation: op, Path: path, Data: data, diff --git a/http/sys_health.go b/http/sys_health.go index 973b79b290..e82a00d12f 100644 --- a/http/sys_health.go +++ b/http/sys_health.go @@ -43,6 +43,7 @@ func fetchStatusCode(r *http.Request, field string) (int, bool, bool) { func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request) { code, body, err := getSysHealth(core, r) + if err != nil { core.Logger().Error("error checking health", "error", err) respondError(w, code, nil) diff --git a/http/sys_monitor_test.go b/http/sys_monitor_test.go new file mode 100644 index 0000000000..97c701fc38 --- /dev/null +++ b/http/sys_monitor_test.go @@ -0,0 +1,82 @@ +package http + +import ( + "context" + "strings" + "testing" + "time" + + log "github.com/hashicorp/go-hclog" + "github.com/hashicorp/vault/helper/testhelpers" + "github.com/hashicorp/vault/sdk/helper/logging" + "github.com/hashicorp/vault/vault" +) + +func TestSysMonitorUnknownLogLevel(t *testing.T) { + cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{HandlerFunc: Handler}) + cluster.Start() + defer cluster.Cleanup() + + client := cluster.Cores[0].Client + request := client.NewRequest("GET", "/v1/sys/monitor") + request.Params.Add("log_level", "haha") + _, err := client.RawRequest(request) + + if err == nil { + t.Fatal("expected to get an error, but didn't") + } else { + if !strings.Contains(err.Error(), "Code: 400") { + t.Fatalf("expected to receive a 400 error, but got %s instead", err) + } + + if !strings.Contains(err.Error(), "unknown log level") { + t.Fatalf("expected to receive a message indicating an unknown log level, but got %s instead", err) + } + } +} + +func TestSysMonitorStreamingLogs(t *testing.T) { + logger := log.NewInterceptLogger(&log.LoggerOptions{ + Output: log.DefaultOutput, + Level: log.Debug, + JSONFormat: logging.ParseEnvLogFormat() == logging.JSONFormat, + }) + + cluster := vault.NewTestCluster(t, nil, &vault.TestClusterOptions{HandlerFunc: Handler, Logger: logger}) + cluster.Start() + defer cluster.Cleanup() + + client := cluster.Cores[0].Client + stopCh := testhelpers.GenerateDebugLogs(t, client) + + debugCount := 0 + ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second) + defer cancel() + logCh, err := client.Sys().Monitor(ctx, "DEBUG") + + if err != nil { + t.Fatal(err) + } + + timeCh := time.After(5 * time.Second) + + for { + select { + case log := <-logCh: + if strings.Contains(log, "[DEBUG]") { + debugCount++ + } + case <-timeCh: + t.Fatal("Failed to get a DEBUG message after 5 seconds") + } + + // If we've seen multiple lines that match what we want, + // it's probably safe to assume streaming is working + if debugCount > 3 { + stopCh <- struct{}{} + break + } + } + + <-stopCh +} diff --git a/sdk/logical/response.go b/sdk/logical/response.go index fb799ba4b8..bc7b235219 100644 --- a/sdk/logical/response.go +++ b/sdk/logical/response.go @@ -185,13 +185,13 @@ func RespondWithStatusCode(resp *Response, req *Request, code int) (*Response, e } // HTTPResponseWriter is optionally added to a request object and can be used to -// write directly to the HTTP response writter. +// write directly to the HTTP response writer. type HTTPResponseWriter struct { http.ResponseWriter written *uint32 } -// NewHTTPResponseWriter creates a new HTTPRepoinseWriter object that wraps the +// NewHTTPResponseWriter creates a new HTTPResponseWriter object that wraps the // provided io.Writer. func NewHTTPResponseWriter(w http.ResponseWriter) *HTTPResponseWriter { return &HTTPResponseWriter{ diff --git a/vault/core.go b/vault/core.go index a64d33591a..a1b5c20c67 100644 --- a/vault/core.go +++ b/vault/core.go @@ -726,22 +726,23 @@ func NewCore(conf *CoreConfig) (*Core, error) { // Setup the core c := &Core{ - entCore: entCore{}, - devToken: conf.DevToken, - physical: conf.Physical, - serviceRegistration: conf.GetServiceRegistration(), - underlyingPhysical: conf.Physical, - storageType: conf.StorageType, - redirectAddr: conf.RedirectAddr, - clusterAddr: new(atomic.Value), - clusterListener: new(atomic.Value), - seal: conf.Seal, - router: NewRouter(), - sealed: new(uint32), - sealMigrated: new(uint32), - standby: true, - baseLogger: conf.Logger, - logger: conf.Logger.Named("core"), + entCore: entCore{}, + devToken: conf.DevToken, + physical: conf.Physical, + serviceRegistration: conf.GetServiceRegistration(), + underlyingPhysical: conf.Physical, + storageType: conf.StorageType, + redirectAddr: conf.RedirectAddr, + clusterAddr: new(atomic.Value), + clusterListener: new(atomic.Value), + seal: conf.Seal, + router: NewRouter(), + sealed: new(uint32), + sealMigrated: new(uint32), + standby: true, + baseLogger: conf.Logger, + logger: conf.Logger.Named("core"), + defaultLeaseTTL: conf.DefaultLeaseTTL, maxLeaseTTL: conf.MaxLeaseTTL, cachingDisabled: conf.DisableCache, @@ -2345,6 +2346,12 @@ func (c *Core) SanitizedConfig() map[string]interface{} { return conf.(*server.Config).Sanitized() } +// LogFormat returns the log format current in use. +func (c *Core) LogFormat() string { + conf := c.rawConfig.Load() + return conf.(*server.Config).LogFormat +} + // MetricsHelper returns the global metrics helper which allows external // packages to access Vault's internal metrics. func (c *Core) MetricsHelper() *metricsutil.MetricsHelper { diff --git a/vault/external_tests/misc/kvv2_upgrade_test.go b/vault/external_tests/misc/kvv2_upgrade_test.go index 330a615354..39d747e8ab 100644 --- a/vault/external_tests/misc/kvv2_upgrade_test.go +++ b/vault/external_tests/misc/kvv2_upgrade_test.go @@ -24,6 +24,7 @@ import ( func TestKVv2_UpgradePaths(t *testing.T) { m := new(sync.Mutex) logOut := new(bytes.Buffer) + logger := hclog.New(&hclog.LoggerOptions{ Output: logOut, Mutex: m, diff --git a/vault/external_tests/misc/recover_from_panic_test.go b/vault/external_tests/misc/recover_from_panic_test.go index 6c2ec1cf42..403b589e29 100644 --- a/vault/external_tests/misc/recover_from_panic_test.go +++ b/vault/external_tests/misc/recover_from_panic_test.go @@ -14,7 +14,6 @@ import ( // https://github.com/hashicorp/vault/pull/6920 func TestRecoverFromPanic(t *testing.T) { logger := hclog.New(nil) - coreConfig := &vault.CoreConfig{ LogicalBackends: map[string]logical.Factory{ "noop": vault.NoopBackendFactory, diff --git a/vault/logical_system.go b/vault/logical_system.go index b1fef7011a..a38991c214 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -21,11 +21,12 @@ import ( "github.com/hashicorp/errwrap" log "github.com/hashicorp/go-hclog" memdb "github.com/hashicorp/go-memdb" - multierror "github.com/hashicorp/go-multierror" + "github.com/hashicorp/go-multierror" uuid "github.com/hashicorp/go-uuid" "github.com/hashicorp/vault/helper/hostutil" "github.com/hashicorp/vault/helper/identity" "github.com/hashicorp/vault/helper/metricsutil" + "github.com/hashicorp/vault/helper/monitor" "github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/physical/raft" "github.com/hashicorp/vault/sdk/framework" @@ -157,6 +158,7 @@ func NewSystemBackend(core *Core, logger log.Logger) *SystemBackend { b.Backend.Paths = append(b.Backend.Paths, b.pprofPaths()...) b.Backend.Paths = append(b.Backend.Paths, b.remountPath()) b.Backend.Paths = append(b.Backend.Paths, b.metricsPath()) + b.Backend.Paths = append(b.Backend.Paths, b.monitorPath()) b.Backend.Paths = append(b.Backend.Paths, b.hostInfoPath()) if core.rawEnabled { @@ -2514,6 +2516,72 @@ func (b *SystemBackend) handleMetrics(ctx context.Context, req *logical.Request, return b.Core.metricsHelper.ResponseForFormat(format), nil } +func (b *SystemBackend) handleMonitor(ctx context.Context, req *logical.Request, data *framework.FieldData) (*logical.Response, error) { + ll := data.Get("log_level").(string) + w := req.ResponseWriter + resp := &logical.Response{} + + if ll == "" { + ll = "info" + } + logLevel := log.LevelFromString(ll) + + if logLevel == log.NoLevel { + return logical.ErrorResponse("unknown log level"), nil + } + + flusher, ok := w.ResponseWriter.(http.Flusher) + if !ok { + return logical.ErrorResponse("streaming not supported"), nil + } + + isJson := b.Core.LogFormat() == "json" + logger := b.Core.Logger().(log.InterceptLogger) + + mon, err := monitor.NewMonitor(512, logger, &log.LoggerOptions{ + Level: logLevel, + JSONFormat: isJson, + }) + defer mon.Stop() + + if err != nil { + return resp, err + } + + logCh := mon.Start() + + if logCh == nil { + return resp, fmt.Errorf("error trying to start a monitor that's already been started") + } + + w.WriteHeader(http.StatusOK) + + // 0 byte write is needed before the Flush call so that if we are using + // a gzip stream it will go ahead and write out the HTTP response header + _, err = w.Write([]byte("")) + if err != nil { + return resp, fmt.Errorf("error seeding flusher: %w", err) + } + + flusher.Flush() + + // Stream logs until the connection is closed. + for { + select { + case <-ctx.Done(): + return resp, nil + case l := <-logCh: + _, err = fmt.Fprint(w, string(l)) + + if err != nil { + return resp, err + } + + flusher.Flush() + } + } +} + // handleHostInfo collects and returns host-related information, which includes // system information, cpu, disk, and memory usage. Any capture-related errors // returned by the collection method will be returned as response warnings. @@ -3400,7 +3468,7 @@ This path responds to the following HTTP methods. Sets the header value for the UI. DELETE /
Clears the header value for UI. - + LIST / List the headers configured for the UI. `, diff --git a/vault/logical_system_paths.go b/vault/logical_system_paths.go index 0613c56262..2bf4495377 100644 --- a/vault/logical_system_paths.go +++ b/vault/logical_system_paths.go @@ -1199,6 +1199,25 @@ func (b *SystemBackend) metricsPath() *framework.Path { } +func (b *SystemBackend) monitorPath() *framework.Path { + return &framework.Path{ + Pattern: "monitor", + Fields: map[string]*framework.FieldSchema{ + "log_level": &framework.FieldSchema{ + Type: framework.TypeString, + Description: "Log level to view system logs at. Currently supported values are \"trace\", \"debug\", \"info\", \"warn\", \"error\".", + Query: true, + }, + }, + Callbacks: map[logical.Operation]framework.OperationFunc{ + logical.ReadOperation: b.handleMonitor, + }, + HelpSynopsis: strings.TrimSpace(sysHelp["monitor"][0]), + HelpDescription: strings.TrimSpace(sysHelp["monitor"][1]), + } + +} + func (b *SystemBackend) hostInfoPath() *framework.Path { return &framework.Path{ Pattern: "host-info/?", diff --git a/vault/testing.go b/vault/testing.go index f1b4542f62..78f7d6a756 100644 --- a/vault/testing.go +++ b/vault/testing.go @@ -14,6 +14,7 @@ import ( "encoding/pem" "errors" "fmt" + "github.com/hashicorp/vault/internalshared/configutil" "io" "io/ioutil" "math/big" @@ -1493,7 +1494,9 @@ func NewTestCluster(t testing.T, base *CoreConfig, opts *TestClusterOptions) *Te } if coreConfig.RawConfig == nil { - coreConfig.RawConfig = new(server.Config) + c := new(server.Config) + c.SharedConfig = &configutil.SharedConfig{LogFormat: logging.UnspecifiedFormat.String()} + coreConfig.RawConfig = c } addAuditBackend := len(coreConfig.AuditBackends) == 0 diff --git a/vendor/github.com/fatih/color/.travis.yml b/vendor/github.com/fatih/color/.travis.yml deleted file mode 100644 index 95f8a1ff5c..0000000000 --- a/vendor/github.com/fatih/color/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: go -go: - - 1.8.x - - tip - diff --git a/vendor/github.com/fatih/color/Gopkg.lock b/vendor/github.com/fatih/color/Gopkg.lock deleted file mode 100644 index 7d879e9caf..0000000000 --- a/vendor/github.com/fatih/color/Gopkg.lock +++ /dev/null @@ -1,27 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - name = "github.com/mattn/go-colorable" - packages = ["."] - revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" - version = "v0.0.9" - -[[projects]] - name = "github.com/mattn/go-isatty" - packages = ["."] - revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" - version = "v0.0.3" - -[[projects]] - branch = "master" - name = "golang.org/x/sys" - packages = ["unix"] - revision = "37707fdb30a5b38865cfb95e5aab41707daec7fd" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - inputs-digest = "e8a50671c3cb93ea935bf210b1cd20702876b9d9226129be581ef646d1565cdc" - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/vendor/github.com/fatih/color/Gopkg.toml b/vendor/github.com/fatih/color/Gopkg.toml deleted file mode 100644 index ff1617f71d..0000000000 --- a/vendor/github.com/fatih/color/Gopkg.toml +++ /dev/null @@ -1,30 +0,0 @@ - -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" - - -[[constraint]] - name = "github.com/mattn/go-colorable" - version = "0.0.9" - -[[constraint]] - name = "github.com/mattn/go-isatty" - version = "0.0.3" diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md index 3fc9544602..42d9abc07e 100644 --- a/vendor/github.com/fatih/color/README.md +++ b/vendor/github.com/fatih/color/README.md @@ -1,6 +1,12 @@ -# Color [![GoDoc](https://godoc.org/github.com/fatih/color?status.svg)](https://godoc.org/github.com/fatih/color) [![Build Status](https://img.shields.io/travis/fatih/color.svg?style=flat-square)](https://travis-ci.org/fatih/color) +# Archived project. No maintenance. + +This project is not maintained anymore and is archived. Feel free to fork and +make your own changes if needed. For more detail read my blog post: [Taking an indefinite sabbatical from my projects](https://arslan.io/2018/10/09/taking-an-indefinite-sabbatical-from-my-projects/) + +Thanks to everyone for their valuable feedback and contributions. +# Color [![GoDoc](https://godoc.org/github.com/fatih/color?status.svg)](https://godoc.org/github.com/fatih/color) Color lets you use colorized outputs in terms of [ANSI Escape Codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors) in Go (Golang). It @@ -17,9 +23,6 @@ suits you. go get github.com/fatih/color ``` -Note that the `vendor` folder is here for stability. Remove the folder if you -already have the dependencies in your GOPATH. - ## Examples ### Standard colors diff --git a/vendor/github.com/fatih/color/go.mod b/vendor/github.com/fatih/color/go.mod new file mode 100644 index 0000000000..bc0df75458 --- /dev/null +++ b/vendor/github.com/fatih/color/go.mod @@ -0,0 +1,8 @@ +module github.com/fatih/color + +go 1.13 + +require ( + github.com/mattn/go-colorable v0.1.4 + github.com/mattn/go-isatty v0.0.11 +) diff --git a/vendor/github.com/fatih/color/go.sum b/vendor/github.com/fatih/color/go.sum new file mode 100644 index 0000000000..44328a8db5 --- /dev/null +++ b/vendor/github.com/fatih/color/go.sum @@ -0,0 +1,8 @@ +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.11 h1:FxPOTFNqGkuDUGi3H/qkUbQO4ZiBa2brKq5r0l8TGeM= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/hashicorp/consul-template/child/child.go b/vendor/github.com/hashicorp/consul-template/child/child.go index 3c94816f59..1b67427073 100644 --- a/vendor/github.com/hashicorp/consul-template/child/child.go +++ b/vendor/github.com/hashicorp/consul-template/child/child.go @@ -290,14 +290,14 @@ func (c *Child) start() error { // down the exit channel. c.stopLock.RLock() defer c.stopLock.RUnlock() - if c.stopped { - return + if !c.stopped { + select { + case <-c.stopCh: + case exitCh <- code: + } } - select { - case <-c.stopCh: - case exitCh <- code: - } + close(exitCh) }() c.exitCh = exitCh @@ -365,16 +365,13 @@ func (c *Child) reload() error { return c.signal(c.reloadSignal) } +// kill sends the signal to kill the process using the configured signal +// if set, else the default system signal func (c *Child) kill(immediately bool) { + if !c.running() { - return - } - - exited := false - process := c.cmd.Process - - if c.cmd.ProcessState != nil { log.Printf("[DEBUG] (child) Kill() called but process dead; not waiting for splay.") + return } else if immediately { log.Printf("[DEBUG] (child) Kill() called but performing immediate shutdown; not waiting for splay.") } else { @@ -384,6 +381,9 @@ func (c *Child) kill(immediately bool) { } } + exited := false + process := c.cmd.Process + if c.killSignal != nil { if err := process.Signal(c.killSignal); err == nil { // Wait a few seconds for it to exit @@ -410,6 +410,11 @@ func (c *Child) kill(immediately bool) { } func (c *Child) running() bool { + select { + case <-c.exitCh: + return false + default: + } return c.cmd != nil && c.cmd.Process != nil } diff --git a/vendor/github.com/hashicorp/consul-template/config/config.go b/vendor/github.com/hashicorp/consul-template/config/config.go index b027040937..a4d31d5a99 100644 --- a/vendor/github.com/hashicorp/consul-template/config/config.go +++ b/vendor/github.com/hashicorp/consul-template/config/config.go @@ -33,6 +33,9 @@ const ( // DefaultKillSignal is the default signal for termination. DefaultKillSignal = syscall.SIGINT + + // DefaultBlockQueryWaitTime is amount of time in seconds to do a blocking query for + DefaultBlockQueryWaitTime = 60 * time.Second ) var ( @@ -48,6 +51,9 @@ type Config struct { // Dedup is used to configure the dedup settings Dedup *DedupConfig `mapstructure:"deduplicate"` + // DefaultDelims is used to configure the default delimiters for templates + DefaultDelims *DefaultDelims `mapstructure:"default_delimiters"` + // Exec is the configuration for exec/supervise mode. Exec *ExecConfig `mapstructure:"exec"` @@ -84,6 +90,9 @@ type Config struct { // Additional command line options // Run once, executing each template exactly once, and exit Once bool + + // BlockQueryWaitTime is amount of time in seconds to do a blocking query for + BlockQueryWaitTime *time.Duration `mapstructure:"block_query_wait"` } // Copy returns a deep copy of the current configuration. This is useful because @@ -104,6 +113,10 @@ func (c *Config) Copy() *Config { o.Dedup = c.Dedup.Copy() } + if c.DefaultDelims != nil { + o.DefaultDelims = c.DefaultDelims.Copy() + } + if c.Exec != nil { o.Exec = c.Exec.Copy() } @@ -136,6 +149,8 @@ func (c *Config) Copy() *Config { o.Once = c.Once + o.BlockQueryWaitTime = c.BlockQueryWaitTime + return &o } @@ -163,6 +178,10 @@ func (c *Config) Merge(o *Config) *Config { r.Dedup = r.Dedup.Merge(o.Dedup) } + if o.DefaultDelims != nil { + r.DefaultDelims = r.DefaultDelims.Merge(o.DefaultDelims) + } + if o.Exec != nil { r.Exec = r.Exec.Merge(o.Exec) } @@ -205,6 +224,8 @@ func (c *Config) Merge(o *Config) *Config { r.Once = o.Once + r.BlockQueryWaitTime = o.BlockQueryWaitTime + return r } @@ -229,6 +250,7 @@ func Parse(s string) (*Config, error) { "consul.ssl", "consul.transport", "deduplicate", + "default_delimiters", "env", "exec", "exec.env", @@ -383,6 +405,7 @@ func (c *Config) GoString() string { return fmt.Sprintf("&Config{"+ "Consul:%#v, "+ "Dedup:%#v, "+ + "DefaultDelims:%#v, "+ "Exec:%#v, "+ "KillSignal:%s, "+ "LogLevel:%s, "+ @@ -394,9 +417,11 @@ func (c *Config) GoString() string { "Vault:%#v, "+ "Wait:%#v,"+ "Once:%#v"+ + "BlockQueryWaitTime:%#v"+ "}", c.Consul, c.Dedup, + c.DefaultDelims, c.Exec, SignalGoString(c.KillSignal), StringGoString(c.LogLevel), @@ -408,6 +433,7 @@ func (c *Config) GoString() string { c.Vault, c.Wait, c.Once, + TimeDurationGoString(c.BlockQueryWaitTime), ) } @@ -436,13 +462,14 @@ func (expected *Config) Diff(actual *Config) string { // variables may be set which control the values for the default configuration. func DefaultConfig() *Config { return &Config{ - Consul: DefaultConsulConfig(), - Dedup: DefaultDedupConfig(), - Exec: DefaultExecConfig(), - Syslog: DefaultSyslogConfig(), - Templates: DefaultTemplateConfigs(), - Vault: DefaultVaultConfig(), - Wait: DefaultWaitConfig(), + Consul: DefaultConsulConfig(), + Dedup: DefaultDedupConfig(), + DefaultDelims: DefaultDefaultDelims(), + Exec: DefaultExecConfig(), + Syslog: DefaultSyslogConfig(), + Templates: DefaultTemplateConfigs(), + Vault: DefaultVaultConfig(), + Wait: DefaultWaitConfig(), } } @@ -465,6 +492,10 @@ func (c *Config) Finalize() { } c.Dedup.Finalize() + if c.DefaultDelims == nil { + c.DefaultDelims = DefaultDefaultDelims() + } + if c.Exec == nil { c.Exec = DefaultExecConfig() } @@ -517,6 +548,11 @@ func (c *Config) Finalize() { if c.Once { c.Wait = &WaitConfig{Enabled: Bool(false)} } + + // defaults WaitTime to 60 seconds + if c.BlockQueryWaitTime == nil { + c.BlockQueryWaitTime = TimeDuration(DefaultBlockQueryWaitTime) + } } func stringFromEnv(list []string, def string) *string { diff --git a/vendor/github.com/hashicorp/consul-template/config/consul.go b/vendor/github.com/hashicorp/consul-template/config/consul.go index ca79ba8b66..9f153c1e7e 100644 --- a/vendor/github.com/hashicorp/consul-template/config/consul.go +++ b/vendor/github.com/hashicorp/consul-template/config/consul.go @@ -8,6 +8,10 @@ type ConsulConfig struct { // Address is the address of the Consul server. It may be an IP or FQDN. Address *string + // Namespace is the Consul namespace to use for reading/writing. This can + // also be set via the CONSUL_NAMESPACE environment variable. + Namespace *string `mapstructure:"namespace"` + // Auth is the HTTP basic authentication for communicating with Consul. Auth *AuthConfig `mapstructure:"auth"` @@ -46,6 +50,8 @@ func (c *ConsulConfig) Copy() *ConsulConfig { o.Address = c.Address + o.Namespace = c.Namespace + if c.Auth != nil { o.Auth = c.Auth.Copy() } @@ -89,6 +95,10 @@ func (c *ConsulConfig) Merge(o *ConsulConfig) *ConsulConfig { r.Address = o.Address } + if o.Namespace != nil { + r.Namespace = o.Namespace + } + if o.Auth != nil { r.Auth = r.Auth.Merge(o.Auth) } @@ -120,6 +130,10 @@ func (c *ConsulConfig) Finalize() { }, "") } + if c.Namespace == nil { + c.Namespace = stringFromEnv([]string{"CONSUL_NAMESPACE"}, "") + } + if c.Auth == nil { c.Auth = DefaultAuthConfig() } @@ -156,6 +170,7 @@ func (c *ConsulConfig) GoString() string { return fmt.Sprintf("&ConsulConfig{"+ "Address:%s, "+ + "Namespace:%s, "+ "Auth:%#v, "+ "Retry:%#v, "+ "SSL:%#v, "+ @@ -163,6 +178,7 @@ func (c *ConsulConfig) GoString() string { "Transport:%#v"+ "}", StringGoString(c.Address), + StringGoString(c.Namespace), c.Auth, c.Retry, c.SSL, diff --git a/vendor/github.com/hashicorp/consul-template/config/dedup.go b/vendor/github.com/hashicorp/consul-template/config/dedup.go index 247855a938..57c6f24a84 100644 --- a/vendor/github.com/hashicorp/consul-template/config/dedup.go +++ b/vendor/github.com/hashicorp/consul-template/config/dedup.go @@ -15,6 +15,9 @@ const ( // DefaultDedupMaxStale is the default max staleness for the deduplication // manager. DefaultDedupMaxStale = DefaultMaxStale + + // DefaultDedupBlockQueryWaitTime is the default amount of time to do a blocking query for the deduplication + DefaultDedupBlockQueryWaitTime = 60 * time.Second ) // DedupConfig is used to enable the de-duplication mode, which depends @@ -32,6 +35,9 @@ type DedupConfig struct { // TTL is the Session TTL used for lock acquisition, defaults to 15 seconds. TTL *time.Duration `mapstructure:"ttl"` + + // BlockQueryWaitTime is amount of time to do a blocking query for, defaults to 60 seconds. + BlockQueryWaitTime *time.Duration `mapstructure:"block_query_wait"` } // DefaultDedupConfig returns a configuration that is populated with the @@ -51,6 +57,7 @@ func (c *DedupConfig) Copy() *DedupConfig { o.MaxStale = c.MaxStale o.Prefix = c.Prefix o.TTL = c.TTL + o.BlockQueryWaitTime = c.BlockQueryWaitTime return &o } @@ -88,6 +95,10 @@ func (c *DedupConfig) Merge(o *DedupConfig) *DedupConfig { r.TTL = o.TTL } + if o.BlockQueryWaitTime != nil { + r.BlockQueryWaitTime = o.BlockQueryWaitTime + } + return r } @@ -97,7 +108,8 @@ func (c *DedupConfig) Finalize() { c.Enabled = Bool(false || TimeDurationPresent(c.MaxStale) || StringPresent(c.Prefix) || - TimeDurationPresent(c.TTL)) + TimeDurationPresent(c.TTL) || + TimeDurationPresent(c.BlockQueryWaitTime)) } if c.MaxStale == nil { @@ -111,6 +123,10 @@ func (c *DedupConfig) Finalize() { if c.TTL == nil { c.TTL = TimeDuration(DefaultDedupTTL) } + + if c.BlockQueryWaitTime == nil { + c.BlockQueryWaitTime = TimeDuration(DefaultDedupBlockQueryWaitTime) + } } // GoString defines the printable version of this struct. @@ -122,11 +138,13 @@ func (c *DedupConfig) GoString() string { "Enabled:%s, "+ "MaxStale:%s, "+ "Prefix:%s, "+ - "TTL:%s"+ + "TTL:%s, "+ + "BlockQueryWaitTime:%s"+ "}", BoolGoString(c.Enabled), TimeDurationGoString(c.MaxStale), StringGoString(c.Prefix), TimeDurationGoString(c.TTL), + TimeDurationGoString(c.BlockQueryWaitTime), ) } diff --git a/vendor/github.com/hashicorp/consul-template/config/default_delimiters.go b/vendor/github.com/hashicorp/consul-template/config/default_delimiters.go new file mode 100644 index 0000000000..bc2a28f861 --- /dev/null +++ b/vendor/github.com/hashicorp/consul-template/config/default_delimiters.go @@ -0,0 +1,53 @@ +package config + +// DefaultDelims is used to configure the default delimiters used for all templates +type DefaultDelims struct { + // Left is the left delimiter for templating + Left *string `mapstructure:"left"` + + // Right is the right delimiter for templating + Right *string `mapstructure:"right"` +} + +// DefaultDefaultDelims returns the default DefaultDelims +func DefaultDefaultDelims() *DefaultDelims { + return &DefaultDelims{} +} + +// Copy returns a copy of the DefaultDelims +func (c *DefaultDelims) Copy() *DefaultDelims { + if c == nil { + return nil + } + + return &DefaultDelims{ + Left: c.Left, + Right: c.Right, + } +} + +// Merge merges the DefaultDelims +func (c *DefaultDelims) Merge(o *DefaultDelims) *DefaultDelims { + if c == nil { + if o == nil { + return nil + } + return o.Copy() + } + + if o == nil { + return c.Copy() + } + + r := c.Copy() + + if o.Left != nil { + r.Left = o.Left + } + + if o.Right != nil { + r.Right = o.Right + } + + return r +} diff --git a/vendor/github.com/hashicorp/consul-template/config/exec.go b/vendor/github.com/hashicorp/consul-template/config/exec.go index 22c7070a46..c3977d48b9 100644 --- a/vendor/github.com/hashicorp/consul-template/config/exec.go +++ b/vendor/github.com/hashicorp/consul-template/config/exec.go @@ -40,8 +40,7 @@ type ExecConfig struct { // EnvConfig is the environmental customizations. Env *EnvConfig `mapstructure:"env"` - // KillSignal is the signal to send to the command to kill it gracefully. The - // default value is "SIGTERM". + // KillSignal is the signal to send to the command to kill it gracefully. KillSignal *os.Signal `mapstructure:"kill_signal"` // KillTimeout is the amount of time to give the process to cleanup before diff --git a/vendor/github.com/hashicorp/consul-template/config/syslog.go b/vendor/github.com/hashicorp/consul-template/config/syslog.go index 0de67199d7..14b9127c29 100644 --- a/vendor/github.com/hashicorp/consul-template/config/syslog.go +++ b/vendor/github.com/hashicorp/consul-template/config/syslog.go @@ -1,16 +1,26 @@ package config -import "fmt" +import ( + "fmt" + + "github.com/hashicorp/consul-template/version" +) const ( // DefaultSyslogFacility is the default facility to log to. DefaultSyslogFacility = "LOCAL0" ) +var ( + // DefaultSyslogName is the default app name in syslog. + DefaultSyslogName = version.Name +) + // SyslogConfig is the configuration for syslog. type SyslogConfig struct { Enabled *bool `mapstructure:"enabled"` Facility *string `mapstructure:"facility"` + Name *string `mapstructure:"name"` } // DefaultSyslogConfig returns a configuration that is populated with the @@ -28,6 +38,7 @@ func (c *SyslogConfig) Copy() *SyslogConfig { var o SyslogConfig o.Enabled = c.Enabled o.Facility = c.Facility + o.Name = c.Name return &o } @@ -57,18 +68,26 @@ func (c *SyslogConfig) Merge(o *SyslogConfig) *SyslogConfig { r.Facility = o.Facility } + if o.Name != nil { + r.Name = o.Name + } + return r } // Finalize ensures there no nil pointers. func (c *SyslogConfig) Finalize() { if c.Enabled == nil { - c.Enabled = Bool(StringPresent(c.Facility)) + c.Enabled = Bool(StringPresent(c.Facility) || StringPresent(c.Name)) } if c.Facility == nil { c.Facility = String(DefaultSyslogFacility) } + + if c.Name == nil { + c.Name = String(DefaultSyslogName) + } } // GoString defines the printable version of this struct. @@ -80,8 +99,10 @@ func (c *SyslogConfig) GoString() string { return fmt.Sprintf("&SyslogConfig{"+ "Enabled:%s, "+ "Facility:%s"+ + "Name:%s"+ "}", BoolGoString(c.Enabled), StringGoString(c.Facility), + StringGoString(c.Name), ) } diff --git a/vendor/github.com/hashicorp/consul-template/config/vault.go b/vendor/github.com/hashicorp/consul-template/config/vault.go index 0ba4cce73a..5eb727c3ae 100644 --- a/vendor/github.com/hashicorp/consul-template/config/vault.go +++ b/vendor/github.com/hashicorp/consul-template/config/vault.go @@ -12,11 +12,6 @@ const ( // vault to version 1.1.0 or newer. EnvVaultSkipVerify = "VAULT_SKIP_VERIFY" - // DefaultVaultGrace is the default grace period before which to read a new - // secret from Vault. If a lease is due to expire in 15 seconds, Consul - // Template will read a new secret at that time minus this value. - DefaultVaultGrace = 15 * time.Second - // DefaultVaultRenewToken is the default value for if the Vault token should // be renewed. DefaultVaultRenewToken = true @@ -42,10 +37,6 @@ type VaultConfig struct { // Enabled controls whether the Vault integration is active. Enabled *bool `mapstructure:"enabled"` - // Grace is the amount of time before a lease is about to expire to force a - // new secret to be read. - Grace *time.Duration `mapstructure:"grace"` - // Namespace is the Vault namespace to use for reading/writing secrets. This can // also be set via the VAULT_NAMESPACE environment variable. Namespace *string `mapstructure:"namespace"` @@ -104,8 +95,6 @@ func (c *VaultConfig) Copy() *VaultConfig { o.Enabled = c.Enabled - o.Grace = c.Grace - o.Namespace = c.Namespace o.RenewToken = c.RenewToken @@ -157,10 +146,6 @@ func (c *VaultConfig) Merge(o *VaultConfig) *VaultConfig { r.Enabled = o.Enabled } - if o.Grace != nil { - r.Grace = o.Grace - } - if o.Namespace != nil { r.Namespace = o.Namespace } @@ -204,24 +189,10 @@ func (c *VaultConfig) Finalize() { }, "") } - if c.Grace == nil { - c.Grace = TimeDuration(DefaultVaultGrace) - } - if c.Namespace == nil { c.Namespace = stringFromEnv([]string{"VAULT_NAMESPACE"}, "") } - if c.RenewToken == nil { - default_renew := DefaultVaultRenewToken - if c.VaultAgentTokenFile != nil { - default_renew = false - } - c.RenewToken = boolFromEnv([]string{ - "VAULT_RENEW_TOKEN", - }, default_renew) - } - if c.Retry == nil { c.Retry = DefaultRetryConfig() } @@ -277,6 +248,19 @@ func (c *VaultConfig) Finalize() { c.Token = stringFromFile([]string{*c.VaultAgentTokenFile}, "") } + // must be after c.Token setting, as default depends on that. + if c.RenewToken == nil { + default_renew := DefaultVaultRenewToken + if c.VaultAgentTokenFile != nil { + default_renew = false + } else if StringVal(c.Token) == "" { + default_renew = false + } + c.RenewToken = boolFromEnv([]string{ + "VAULT_RENEW_TOKEN", + }, default_renew) + } + if c.Transport == nil { c.Transport = DefaultTransportConfig() } @@ -302,7 +286,6 @@ func (c *VaultConfig) GoString() string { return fmt.Sprintf("&VaultConfig{"+ "Address:%s, "+ "Enabled:%s, "+ - "Grace:%s, "+ "Namespace:%s,"+ "RenewToken:%s, "+ "Retry:%#v, "+ @@ -314,7 +297,6 @@ func (c *VaultConfig) GoString() string { "}", StringGoString(c.Address), BoolGoString(c.Enabled), - TimeDurationGoString(c.Grace), StringGoString(c.Namespace), BoolGoString(c.RenewToken), c.Retry, diff --git a/vendor/github.com/hashicorp/consul-template/dependency/client_set.go b/vendor/github.com/hashicorp/consul-template/dependency/client_set.go index e2bceb7738..b891f3a39f 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/client_set.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/client_set.go @@ -38,6 +38,7 @@ type vaultClient struct { // CreateConsulClientInput is used as input to the CreateConsulClient function. type CreateConsulClientInput struct { Address string + Namespace string Token string AuthEnabled bool AuthUsername string @@ -95,6 +96,10 @@ func (c *ClientSet) CreateConsulClient(i *CreateConsulClientInput) error { consulConfig.Address = i.Address } + if i.Namespace != "" { + consulConfig.Namespace = i.Namespace + } + if i.Token != "" { consulConfig.Token = i.Token } diff --git a/vendor/github.com/hashicorp/consul-template/dependency/connect_ca.go b/vendor/github.com/hashicorp/consul-template/dependency/connect_ca.go new file mode 100644 index 0000000000..0e8036df08 --- /dev/null +++ b/vendor/github.com/hashicorp/consul-template/dependency/connect_ca.go @@ -0,0 +1,72 @@ +package dependency + +import ( + "log" + "net/url" + + "github.com/pkg/errors" +) + +var ( + // Ensure implements + _ Dependency = (*ConnectCAQuery)(nil) +) + +type ConnectCAQuery struct { + stopCh chan struct{} +} + +func NewConnectCAQuery() *ConnectCAQuery { + return &ConnectCAQuery{ + stopCh: make(chan struct{}, 1), + } +} + +func (d *ConnectCAQuery) Fetch(clients *ClientSet, opts *QueryOptions) ( + interface{}, *ResponseMetadata, error, +) { + select { + case <-d.stopCh: + return nil, nil, ErrStopped + default: + } + + opts = opts.Merge(nil) + log.Printf("[TRACE] %s: GET %s", d, &url.URL{ + Path: "/v1/agent/connect/ca/roots", + RawQuery: opts.String(), + }) + + certs, md, err := clients.Consul().Agent().ConnectCARoots( + opts.ToConsulOpts()) + if err != nil { + return nil, nil, errors.Wrap(err, d.String()) + } + + log.Printf("[TRACE] %s: returned %d results", d, len(certs.Roots)) + log.Printf("[TRACE] %s: %#v ", d, md) + + rm := &ResponseMetadata{ + LastIndex: md.LastIndex, + LastContact: md.LastContact, + Block: true, + } + + return certs.Roots, rm, nil +} + +func (d *ConnectCAQuery) Stop() { + close(d.stopCh) +} + +func (d *ConnectCAQuery) CanShare() bool { + return false +} + +func (d *ConnectCAQuery) Type() Type { + return TypeConsul +} + +func (d *ConnectCAQuery) String() string { + return "connect.caroots" +} diff --git a/vendor/github.com/hashicorp/consul-template/dependency/connect_leaf.go b/vendor/github.com/hashicorp/consul-template/dependency/connect_leaf.go new file mode 100644 index 0000000000..bd5fd35cbb --- /dev/null +++ b/vendor/github.com/hashicorp/consul-template/dependency/connect_leaf.go @@ -0,0 +1,77 @@ +package dependency + +import ( + "fmt" + "log" + "net/url" + + "github.com/pkg/errors" +) + +var ( + // Ensure implements + _ Dependency = (*ConnectLeafQuery)(nil) +) + +type ConnectLeafQuery struct { + stopCh chan struct{} + + service string +} + +func NewConnectLeafQuery(service string) *ConnectLeafQuery { + return &ConnectLeafQuery{ + stopCh: make(chan struct{}, 1), + service: service, + } +} + +func (d *ConnectLeafQuery) Fetch(clients *ClientSet, opts *QueryOptions) ( + interface{}, *ResponseMetadata, error, +) { + select { + case <-d.stopCh: + return nil, nil, ErrStopped + default: + } + opts = opts.Merge(nil) + log.Printf("[TRACE] %s: GET %s", d, &url.URL{ + Path: "/v1/agent/connect/ca/leaf/" + d.service, + RawQuery: opts.String(), + }) + + cert, md, err := clients.Consul().Agent().ConnectCALeaf(d.service, + opts.ToConsulOpts()) + if err != nil { + return nil, nil, errors.Wrap(err, d.String()) + } + + log.Printf("[TRACE] %s: returned response", d) + + rm := &ResponseMetadata{ + LastIndex: md.LastIndex, + LastContact: md.LastContact, + Block: true, + } + + return cert, rm, nil +} + +func (d *ConnectLeafQuery) Stop() { + close(d.stopCh) +} + +func (d *ConnectLeafQuery) CanShare() bool { + return false +} + +func (d *ConnectLeafQuery) Type() Type { + return TypeConsul +} + +func (d *ConnectLeafQuery) String() string { + if d.service != "" { + return fmt.Sprintf("connect.caleaf(%s)", d.service) + } + return "connect.caleaf" +} diff --git a/vendor/github.com/hashicorp/consul-template/dependency/health_service.go b/vendor/github.com/hashicorp/consul-template/dependency/health_service.go index 215f53d0d2..9419925319 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/health_service.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/health_service.go @@ -51,6 +51,7 @@ type HealthService struct { Checks api.HealthChecks Status string Port int + Weights api.AgentWeights } // HealthServiceQuery is the representation of all a service query in Consul. @@ -62,10 +63,20 @@ type HealthServiceQuery struct { name string near string tag string + connect bool } // NewHealthServiceQuery processes the strings to build a service dependency. func NewHealthServiceQuery(s string) (*HealthServiceQuery, error) { + return healthServiceQuery(s, false) +} + +// NewHealthConnect Query processes the strings to build a connect dependency. +func NewHealthConnectQuery(s string) (*HealthServiceQuery, error) { + return healthServiceQuery(s, true) +} + +func healthServiceQuery(s string, connect bool) (*HealthServiceQuery, error) { if !HealthServiceQueryRe.MatchString(s) { return nil, fmt.Errorf("health.service: invalid format: %q", s) } @@ -86,7 +97,8 @@ func NewHealthServiceQuery(s string) (*HealthServiceQuery, error) { filters = append(filters, f) case "": default: - return nil, fmt.Errorf("health.service: invalid filter: %q in %q", f, s) + return nil, fmt.Errorf( + "health.service: invalid filter: %q in %q", f, s) } } sort.Strings(filters) @@ -101,6 +113,7 @@ func NewHealthServiceQuery(s string) (*HealthServiceQuery, error) { name: m["name"], near: m["near"], tag: m["tag"], + connect: connect, }, nil } @@ -130,10 +143,15 @@ func (d *HealthServiceQuery) Fetch(clients *ClientSet, opts *QueryOptions) (inte log.Printf("[TRACE] %s: GET %s", d, u) // Check if a user-supplied filter was given. If so, we may be querying for - // more than healthy services, so we need to implement client-side filtering. + // more than healthy services, so we need to implement client-side + // filtering. passingOnly := len(d.filters) == 1 && d.filters[0] == HealthPassing - entries, qm, err := clients.Consul().Health().Service(d.name, d.tag, passingOnly, opts.ToConsulOpts()) + nodes := clients.Consul().Health().Service + if d.connect { + nodes = clients.Consul().Health().Connect + } + entries, qm, err := nodes(d.name, d.tag, passingOnly, opts.ToConsulOpts()) if err != nil { return nil, nil, errors.Wrap(err, d.String()) } @@ -145,13 +163,14 @@ func (d *HealthServiceQuery) Fetch(clients *ClientSet, opts *QueryOptions) (inte // Get the status of this service from its checks. status := entry.Checks.AggregatedStatus() - // If we are not checking only healthy services, filter out services that do - // not match the given filter. + // If we are not checking only healthy services, filter out services + // that do not match the given filter. if !acceptStatus(d.filters, status) { continue } - // Get the address of the service, falling back to the address of the node. + // Get the address of the service, falling back to the address of the + // node. address := entry.Service.Address if address == "" { address = entry.Node.Address @@ -167,10 +186,12 @@ func (d *HealthServiceQuery) Fetch(clients *ClientSet, opts *QueryOptions) (inte Address: address, ID: entry.Service.ID, Name: entry.Service.Service, - Tags: ServiceTags(deepCopyAndSortTags(entry.Service.Tags)), - Status: status, - Checks: entry.Checks, - Port: entry.Service.Port, + Tags: ServiceTags( + deepCopyAndSortTags(entry.Service.Tags)), + Status: status, + Checks: entry.Checks, + Port: entry.Service.Port, + Weights: entry.Service.Weights, }) } diff --git a/vendor/github.com/hashicorp/consul-template/dependency/vault_common.go b/vendor/github.com/hashicorp/consul-template/dependency/vault_common.go index 6abe69cfd1..f21305fcbe 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/vault_common.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/vault_common.go @@ -8,6 +8,7 @@ import ( "time" "crypto/x509" + "encoding/json" "encoding/pem" "github.com/hashicorp/vault/api" @@ -141,6 +142,20 @@ func leaseCheckWait(s *Secret) time.Duration { } } + // Handle if this is a secret with a rotation period. If this is a rotating secret, + // the rotating secret's TTL will be the duration to sleep before rendering the new secret. + var rotatingSecret bool + if _, ok := s.Data["rotation_period"]; ok && s.LeaseID == "" { + if ttlInterface, ok := s.Data["ttl"]; ok { + if ttlData, err := ttlInterface.(json.Number).Int64(); err == nil { + log.Printf("[DEBUG] Found rotation_period and set lease duration to %d seconds", ttlData) + // Add a second for cushion + base = int(ttlData) + 1 + rotatingSecret = true + } + } + } + // Ensure we have a lease duration, since sometimes this can be zero. if base <= 0 { base = int(VaultDefaultLeaseDuration.Seconds()) @@ -156,7 +171,9 @@ func leaseCheckWait(s *Secret) time.Duration { // Use some randomness so many clients do not hit Vault simultaneously. sleep = sleep * (rand.Float64() + 1) / 2.0 - } else { + } else if !rotatingSecret { + // If the secret doesn't have a rotation period, this is a non-renewable leased + // secret. // For non-renewable leases set the renew duration to use much of the secret // lease as possible. Use a stagger over 85%-95% of the lease duration so that // many clients do not hit Vault simultaneously. @@ -339,8 +356,12 @@ func addPrefixToVKVPath(p, mountPath, apiPrefix string) string { return path.Join(mountPath, apiPrefix) default: p = strings.TrimPrefix(p, mountPath) - // Don't add /data to the path if it's been added manually. - if strings.HasPrefix(p, apiPrefix) { + // Don't add /data/ to the path if it's been added manually. + apiPathPrefix := apiPrefix + if !strings.HasSuffix(apiPrefix, "/") { + apiPathPrefix += "/" + } + if strings.HasPrefix(p, apiPathPrefix) { return path.Join(mountPath, p) } return path.Join(mountPath, apiPrefix, p) diff --git a/vendor/github.com/hashicorp/consul-template/dependency/vault_read.go b/vendor/github.com/hashicorp/consul-template/dependency/vault_read.go index 00ebf27ec0..8f24f42db2 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/vault_read.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/vault_read.go @@ -122,6 +122,9 @@ func (d *VaultReadQuery) Stop() { // String returns the human-friendly version of this dependency. func (d *VaultReadQuery) String() string { + if v := d.queryValues["version"]; len(v) > 0 { + return fmt.Sprintf("vault.read(%s.v%s)", d.rawPath, v[0]) + } return fmt.Sprintf("vault.read(%s)", d.rawPath) } diff --git a/vendor/github.com/hashicorp/consul-template/dependency/vault_token.go b/vendor/github.com/hashicorp/consul-template/dependency/vault_token.go index 61fa29cfa0..93ad5984ac 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/vault_token.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/vault_token.go @@ -1,10 +1,8 @@ package dependency import ( - "log" - "time" - "github.com/hashicorp/vault/api" + "github.com/pkg/errors" ) var ( @@ -36,7 +34,8 @@ func NewVaultTokenQuery(token string) (*VaultTokenQuery, error) { } // Fetch queries the Vault API -func (d *VaultTokenQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interface{}, *ResponseMetadata, error) { +func (d *VaultTokenQuery) Fetch(clients *ClientSet, opts *QueryOptions, +) (interface{}, *ResponseMetadata, error) { select { case <-d.stopCh: return nil, nil, ErrStopped @@ -44,25 +43,13 @@ func (d *VaultTokenQuery) Fetch(clients *ClientSet, opts *QueryOptions) (interfa } if vaultSecretRenewable(d.secret) { + err := renewSecret(clients, d) + if err != nil { + return nil, nil, errors.Wrap(err, d.String()) + } renewSecret(clients, d) } - // The secret isn't renewable, probably the generic secret backend. - // TODO This is incorrect when given a non-renewable template. We should - // instead to a lookup self to determine the lease duration. - opts = opts.Merge(&QueryOptions{}) - dur := leaseCheckWait(d.secret) - if dur < opts.VaultGrace { - dur = opts.VaultGrace - } - - log.Printf("[TRACE] %s: token is not renewable, sleeping for %s", d, dur) - select { - case <-time.After(dur): - case <-d.stopCh: - return nil, nil, ErrStopped - } - return nil, nil, ErrLeaseExpired } diff --git a/vendor/github.com/hashicorp/consul-template/logging/logging.go b/vendor/github.com/hashicorp/consul-template/logging/logging.go index 82c4eacc1d..72f76b5e68 100644 --- a/vendor/github.com/hashicorp/consul-template/logging/logging.go +++ b/vendor/github.com/hashicorp/consul-template/logging/logging.go @@ -16,15 +16,14 @@ var Levels = []logutils.LogLevel{"TRACE", "DEBUG", "INFO", "WARN", "ERR"} // Config is the configuration for this log setup. type Config struct { - // Name is the progname as it will appear in syslog output (if enabled). - Name string `json:"name"` - // Level is the log level to use. Level string `json:"level"` // Syslog and SyslogFacility are the syslog configuration options. Syslog bool `json:"syslog"` SyslogFacility string `json:"syslog_facility"` + // SyslogName is the progname as it will appear in syslog output (if enabled). + SyslogName string `json:"name"` // Writer is the output where logs should go. If syslog is enabled, data will // be written to writer in addition to syslog. @@ -51,7 +50,7 @@ func Setup(config *Config) error { if config.Syslog { log.Printf("[DEBUG] (logging) enabling syslog on %s", config.SyslogFacility) - l, err := gsyslog.NewLogger(gsyslog.LOG_NOTICE, config.SyslogFacility, config.Name) + l, err := gsyslog.NewLogger(gsyslog.LOG_NOTICE, config.SyslogFacility, config.SyslogName) if err != nil { return fmt.Errorf("error setting up syslog logger: %s", err) } diff --git a/vendor/github.com/hashicorp/consul-template/manager/runner.go b/vendor/github.com/hashicorp/consul-template/manager/runner.go index 877f4bf945..9da7a9d342 100644 --- a/vendor/github.com/hashicorp/consul-template/manager/runner.go +++ b/vendor/github.com/hashicorp/consul-template/manager/runner.go @@ -556,23 +556,6 @@ func (r *Runner) Run() error { } } - // Check if we need to deliver any rendered signals - if wouldRenderAny || renderedAny { - // Send the signal that a template got rendered - select { - case r.renderedCh <- struct{}{}: - default: - } - } - - // Check if we need to deliver any event signals - if newRenderEvent { - select { - case r.renderEventCh <- struct{}{}: - default: - } - } - // Perform the diff and update the known dependencies. r.diffAndUpdateDeps(runCtx.depsMap) @@ -601,6 +584,23 @@ func (r *Runner) Run() error { } } + // Check if we need to deliver any rendered signals + if wouldRenderAny || renderedAny { + // Send the signal that a template got rendered + select { + case r.renderedCh <- struct{}{}: + default: + } + } + + // Check if we need to deliver any event signals + if newRenderEvent { + select { + case r.renderEventCh <- struct{}{}: + default: + } + } + // If we got this far and have a child process, we need to send the reload // signal to the child process. if renderedAny && r.child != nil { @@ -691,12 +691,20 @@ func (r *Runner) runTemplate(tmpl *template.Template, runCtx *templateRunCtx) (* // Grab the list of used and missing dependencies. missing, used := result.Missing, result.Used + if l := missing.Len(); l > 0 { + log.Printf("[DEBUG] (runner) missing data for %d dependencies", l) + for _, missingDependency := range missing.List() { + log.Printf("[DEBUG] (runner) missing dependency: %s", missingDependency) + } + } + // Add the dependency to the list of dependencies for this runner. for _, d := range used.List() { // If we've taken over leadership for a template, we may have data // that is cached, but not have the watcher. We must treat this as // missing so that we create the watcher and re-run the template. if isLeader && !r.watcher.Watching(d) { + log.Printf("[DEBUG] (runner) add used dependency %s to missing since isLeader but do not have a watcher", d) missing.Add(d) } if _, ok := runCtx.depsMap[d.String()]; !ok { @@ -865,12 +873,21 @@ func (r *Runner) init() error { // config templates is kept so templates can lookup their commands and output // destinations. for _, ctmpl := range *r.config.Templates { + leftDelim := config.StringVal(ctmpl.LeftDelim) + if leftDelim == "" { + leftDelim = config.StringVal(r.config.DefaultDelims.Left) + } + rightDelim := config.StringVal(ctmpl.RightDelim) + if rightDelim == "" { + rightDelim = config.StringVal(r.config.DefaultDelims.Right) + } + tmpl, err := template.NewTemplate(&template.NewTemplateInput{ Source: config.StringVal(ctmpl.Source), Contents: config.StringVal(ctmpl.Contents), ErrMissingKey: config.BoolVal(ctmpl.ErrMissingKey), - LeftDelim: config.StringVal(ctmpl.LeftDelim), - RightDelim: config.StringVal(ctmpl.RightDelim), + LeftDelim: leftDelim, + RightDelim: rightDelim, FunctionBlacklist: ctmpl.FunctionBlacklist, SandboxPath: config.StringVal(ctmpl.SandboxPath), }) @@ -1232,6 +1249,7 @@ func newClientSet(c *config.Config) (*dep.ClientSet, error) { if err := clients.CreateConsulClient(&dep.CreateConsulClientInput{ Address: config.StringVal(c.Consul.Address), + Namespace: config.StringVal(c.Consul.Namespace), Token: config.StringVal(c.Consul.Token), AuthEnabled: config.BoolVal(c.Consul.Auth.Enabled), AuthUsername: config.StringVal(c.Consul.Auth.Username), @@ -1288,6 +1306,7 @@ func newWatcher(c *config.Config, clients *dep.ClientSet, once bool) (*watch.Wat Clients: clients, MaxStale: config.TimeDurationVal(c.MaxStale), Once: c.Once, + BlockQueryWaitTime: config.TimeDurationVal(c.BlockQueryWaitTime), RenewVault: clients.Vault().Token() != "" && config.BoolVal(c.Vault.RenewToken), VaultAgentTokenFile: config.StringVal(c.Vault.VaultAgentTokenFile), RetryFuncConsul: watch.RetryFunc(c.Consul.Retry.RetryFunc()), @@ -1295,7 +1314,6 @@ func newWatcher(c *config.Config, clients *dep.ClientSet, once bool) (*watch.Wat // dependencies like reading a file from disk. RetryFuncDefault: nil, RetryFuncVault: watch.RetryFunc(c.Vault.Retry.RetryFunc()), - VaultGrace: config.TimeDurationVal(c.Vault.Grace), VaultToken: clients.Vault().Token(), }) if err != nil { diff --git a/vendor/github.com/hashicorp/consul-template/template/funcs.go b/vendor/github.com/hashicorp/consul-template/template/funcs.go index 2114279ca7..acf8e70a44 100644 --- a/vendor/github.com/hashicorp/consul-template/template/funcs.go +++ b/vendor/github.com/hashicorp/consul-template/template/funcs.go @@ -2,7 +2,9 @@ package template import ( "bytes" + "crypto/sha256" "encoding/base64" + "encoding/hex" "encoding/json" "fmt" "io/ioutil" @@ -19,6 +21,7 @@ import ( "github.com/BurntSushi/toml" dep "github.com/hashicorp/consul-template/dependency" + "github.com/hashicorp/consul/api" socktmpl "github.com/hashicorp/go-sockaddr/template" "github.com/pkg/errors" yaml "gopkg.in/yaml.v2" @@ -387,10 +390,8 @@ func byMeta(meta string, services []*dep.HealthService) (groups map[string][]*de } getOrDefault := func(m map[string]string, key string) string { realKey := strings.TrimSuffix(key, "|int") - if val, ok := m[realKey]; ok { - if val != "" { - return val - } + if val := m[realKey]; val != "" { + return val } if strings.HasSuffix(key, "|int") { return "0" @@ -472,6 +473,62 @@ func servicesFunc(b *Brain, used, missing *dep.Set) func(...string) ([]*dep.Cata } } +// connectFunc returns or accumulates health connect dependencies. +func connectFunc(b *Brain, used, missing *dep.Set) func(...string) ([]*dep.HealthService, error) { + return func(s ...string) ([]*dep.HealthService, error) { + result := []*dep.HealthService{} + + if len(s) == 0 || s[0] == "" { + return result, nil + } + + d, err := dep.NewHealthConnectQuery(strings.Join(s, "|")) + if err != nil { + return nil, err + } + + used.Add(d) + + if value, ok := b.Recall(d); ok { + return value.([]*dep.HealthService), nil + } + + missing.Add(d) + + return result, nil + } +} + +func connectCARootsFunc(b *Brain, used, missing *dep.Set, +) func(...string) ([]*api.CARoot, error) { + return func(...string) ([]*api.CARoot, error) { + d := dep.NewConnectCAQuery() + used.Add(d) + if value, ok := b.Recall(d); ok { + return value.([]*api.CARoot), nil + } + missing.Add(d) + return nil, nil + } +} + +func connectLeafFunc(b *Brain, used, missing *dep.Set, +) func(...string) (*api.LeafCert, error) { + return func(s ...string) (*api.LeafCert, error) { + if len(s) == 0 || s[0] == "" { + return nil, nil + } + d := dep.NewConnectLeafQuery(s[0]) + used.Add(d) + if value, ok := b.Recall(d); ok { + return value.(*api.LeafCert), nil + } + missing.Add(d) + return nil, nil + + } +} + func safeTreeFunc(b *Brain, used, missing *dep.Set) func(string) ([]*dep.KeyPair, error) { // call treeFunc but explicitly mark that empty data set returned on monitored KV prefix is NOT safe return treeFunc(b, used, missing, false) @@ -805,9 +862,11 @@ func loop(ifaces ...interface{}) (<-chan int64, error) { to64 := func(i interface{}) (int64, error) { v := reflect.ValueOf(i) switch v.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, + reflect.Int64: return int64(v.Int()), nil - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32: + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, + reflect.Uint64: return int64(v.Uint()), nil case reflect.String: return parseInt(v.String()) @@ -922,6 +981,19 @@ func parseUint(s string) (uint64, error) { return result, nil } +// parseYAML returns a structure for valid YAML +func parseYAML(s string) (interface{}, error) { + if s == "" { + return map[string]interface{}{}, nil + } + + var data interface{} + if err := yaml.Unmarshal([]byte(s), &data); err != nil { + return nil, err + } + return data, nil +} + // plugin executes a subprocess as the given command string. It is assumed the // resulting command returns JSON which is then parsed and returned as the // value for use in the template. @@ -1287,6 +1359,148 @@ func modulo(b, a interface{}) (interface{}, error) { } } +// minimum returns the minimum between a and b. +func minimum(b, a interface{}) (interface{}, error) { + av := reflect.ValueOf(a) + bv := reflect.ValueOf(b) + + switch av.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + switch bv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if av.Int() < bv.Int() { + return av.Int(), nil + } + return bv.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if av.Int() < int64(bv.Uint()) { + return av.Int(), nil + } + return bv.Uint(), nil + case reflect.Float32, reflect.Float64: + if float64(av.Int()) < bv.Float() { + return av.Int(), nil + } + return bv.Float(), nil + default: + return nil, fmt.Errorf("minimum: unknown type for %q (%T)", bv, b) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + switch bv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if int64(av.Uint()) < bv.Int() { + return av.Uint(), nil + } + return bv.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if av.Uint() < bv.Uint() { + return av.Uint(), nil + } + return bv.Uint(), nil + case reflect.Float32, reflect.Float64: + if float64(av.Uint()) < bv.Float() { + return av.Uint(), nil + } + return bv.Float(), nil + default: + return nil, fmt.Errorf("minimum: unknown type for %q (%T)", bv, b) + } + case reflect.Float32, reflect.Float64: + switch bv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if av.Float() < float64(bv.Int()) { + return av.Float(), nil + } + return bv.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if av.Float() < float64(bv.Uint()) { + return av.Float(), nil + } + return bv.Uint(), nil + case reflect.Float32, reflect.Float64: + if av.Float() < bv.Float() { + return av.Float(), nil + } + return bv.Float(), nil + default: + return nil, fmt.Errorf("minimum: unknown type for %q (%T)", bv, b) + } + default: + return nil, fmt.Errorf("minimum: unknown type for %q (%T)", av, a) + } +} + +// maximum returns the maximum between a and b. +func maximum(b, a interface{}) (interface{}, error) { + av := reflect.ValueOf(a) + bv := reflect.ValueOf(b) + + switch av.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + switch bv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if av.Int() > bv.Int() { + return av.Int(), nil + } + return bv.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if av.Int() > int64(bv.Uint()) { + return av.Int(), nil + } + return bv.Uint(), nil + case reflect.Float32, reflect.Float64: + if float64(av.Int()) > bv.Float() { + return av.Int(), nil + } + return bv.Float(), nil + default: + return nil, fmt.Errorf("maximum: unknown type for %q (%T)", bv, b) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + switch bv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if int64(av.Uint()) > bv.Int() { + return av.Uint(), nil + } + return bv.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if av.Uint() > bv.Uint() { + return av.Uint(), nil + } + return bv.Uint(), nil + case reflect.Float32, reflect.Float64: + if float64(av.Uint()) > bv.Float() { + return av.Uint(), nil + } + return bv.Float(), nil + default: + return nil, fmt.Errorf("maximum: unknown type for %q (%T)", bv, b) + } + case reflect.Float32, reflect.Float64: + switch bv.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if av.Float() > float64(bv.Int()) { + return av.Float(), nil + } + return bv.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + if av.Float() > float64(bv.Uint()) { + return av.Float(), nil + } + return bv.Uint(), nil + case reflect.Float32, reflect.Float64: + if av.Float() > bv.Float() { + return av.Float(), nil + } + return bv.Float(), nil + default: + return nil, fmt.Errorf("maximum: unknown type for %q (%T)", bv, b) + } + default: + return nil, fmt.Errorf("maximum: unknown type for %q (%T)", av, a) + } +} + // blacklisted always returns an error, to be used in place of blacklisted template functions func blacklisted(...string) (string, error) { return "", errors.New("function is disabled") @@ -1313,10 +1527,18 @@ func pathInSandbox(sandbox, path string) error { // sockaddr wraps go-sockaddr templating func sockaddr(args ...string) (string, error) { - t := fmt.Sprintf("{{ %s }} ", strings.Join(args, " ")) + t := fmt.Sprintf("{{ %s }}", strings.Join(args, " ")) k, err := socktmpl.Parse(t) if err != nil { return "", err } return k, nil } + +// sha256Hex return the sha256 hex of a string +func sha256Hex(item string) (string, error) { + h := sha256.New() + h.Write([]byte(item)) + output := hex.EncodeToString(h.Sum(nil)) + return output, nil +} diff --git a/vendor/github.com/hashicorp/consul-template/template/template.go b/vendor/github.com/hashicorp/consul-template/template/template.go index 36da551834..f95ad3e882 100644 --- a/vendor/github.com/hashicorp/consul-template/template/template.go +++ b/vendor/github.com/hashicorp/consul-template/template/template.go @@ -15,12 +15,12 @@ import ( var ( // ErrTemplateContentsAndSource is the error returned when a template // specifies both a "source" and "content" argument, which is not valid. - ErrTemplateContentsAndSource = errors.New("template: cannot specify both 'source' and 'content'") + ErrTemplateContentsAndSource = errors.New("template: cannot specify both 'source' and 'contents'") // ErrTemplateMissingContentsAndSource is the error returned when a template // does not specify either a "source" or "content" argument, which is not // valid. - ErrTemplateMissingContentsAndSource = errors.New("template: must specify exactly one of 'source' or 'content'") + ErrTemplateMissingContentsAndSource = errors.New("template: must specify exactly one of 'source' or 'contents'") ) // Template is the internal representation of an individual template to process. @@ -237,9 +237,12 @@ func funcMap(i *funcMapInput) template.FuncMap { "secret": secretFunc(i.brain, i.used, i.missing), "secrets": secretsFunc(i.brain, i.used, i.missing), "service": serviceFunc(i.brain, i.used, i.missing), + "connect": connectFunc(i.brain, i.used, i.missing), "services": servicesFunc(i.brain, i.used, i.missing), "tree": treeFunc(i.brain, i.used, i.missing, true), "safeTree": safeTreeFunc(i.brain, i.used, i.missing), + "caRoots": connectCARootsFunc(i.brain, i.used, i.missing), + "caLeaf": connectLeafFunc(i.brain, i.used, i.missing), // Scratch "scratch": func() *Scratch { return &scratch }, @@ -270,10 +273,12 @@ func funcMap(i *funcMapInput) template.FuncMap { "parseInt": parseInt, "parseJSON": parseJSON, "parseUint": parseUint, + "parseYAML": parseYAML, "plugin": plugin, "regexReplaceAll": regexReplaceAll, "regexMatch": regexMatch, "replaceAll": replaceAll, + "sha256Hex": sha256Hex, "timestamp": timestamp, "toLower": toLower, "toJSON": toJSON, @@ -291,6 +296,8 @@ func funcMap(i *funcMapInput) template.FuncMap { "multiply": multiply, "divide": divide, "modulo": modulo, + "minimum": minimum, + "maximum": maximum, } for _, bf := range i.functionBlacklist { diff --git a/vendor/github.com/hashicorp/consul-template/version/version.go b/vendor/github.com/hashicorp/consul-template/version/version.go index c0d0a6919c..d014080922 100644 --- a/vendor/github.com/hashicorp/consul-template/version/version.go +++ b/vendor/github.com/hashicorp/consul-template/version/version.go @@ -2,7 +2,7 @@ package version import "fmt" -const Version = "0.22.0" +const Version = "0.25.0" var ( Name string diff --git a/vendor/github.com/hashicorp/consul-template/watch/view.go b/vendor/github.com/hashicorp/consul-template/watch/view.go index bcef6c0b21..bb5662b9fa 100644 --- a/vendor/github.com/hashicorp/consul-template/watch/view.go +++ b/vendor/github.com/hashicorp/consul-template/watch/view.go @@ -11,11 +11,6 @@ import ( dep "github.com/hashicorp/consul-template/dependency" ) -const ( - // The amount of time to do a blocking query for - defaultWaitTime = 60 * time.Second -) - // View is a representation of a Dependency and the most recent data it has // received from Consul. type View struct { @@ -33,6 +28,9 @@ type View struct { receivedData bool lastIndex uint64 + // blockQueryWaitTime is amount of time in seconds to do a blocking query for + blockQueryWaitTime time.Duration + // maxStale is the maximum amount of time to allow a query to be stale. maxStale time.Duration @@ -45,11 +43,6 @@ type View struct { // stopCh is used to stop polling on this View stopCh chan struct{} - - // vaultGrace is the grace period between a lease and the max TTL for which - // Consul Template will generate a new secret instead of renewing an existing - // one. - vaultGrace time.Duration } // NewViewInput is used as input to the NewView function. @@ -61,6 +54,9 @@ type NewViewInput struct { // directly to the dependency. Clients *dep.ClientSet + // BlockQueryWaitTime is amount of time in seconds to do a blocking query for + BlockQueryWaitTime time.Duration + // MaxStale is the maximum amount a time a query response is allowed to be // stale before forcing a read from the leader. MaxStale time.Duration @@ -71,23 +67,18 @@ type NewViewInput struct { // RetryFunc is a function which dictates how this view should retry on // upstream errors. RetryFunc RetryFunc - - // VaultGrace is the grace period between a lease and the max TTL for which - // Consul Template will generate a new secret instead of renewing an existing - // one. - VaultGrace time.Duration } // NewView constructs a new view with the given inputs. func NewView(i *NewViewInput) (*View, error) { return &View{ - dependency: i.Dependency, - clients: i.Clients, - maxStale: i.MaxStale, - once: i.Once, - retryFunc: i.RetryFunc, - stopCh: make(chan struct{}, 1), - vaultGrace: i.VaultGrace, + dependency: i.Dependency, + clients: i.Clients, + blockQueryWaitTime: i.BlockQueryWaitTime, + maxStale: i.MaxStale, + once: i.Once, + retryFunc: i.RetryFunc, + stopCh: make(chan struct{}, 1), }, nil } @@ -212,9 +203,8 @@ func (v *View) fetch(doneCh, successCh chan<- struct{}, errCh chan<- error) { data, rm, err := v.dependency.Fetch(v.clients, &dep.QueryOptions{ AllowStale: allowStale, - WaitTime: defaultWaitTime, + WaitTime: v.blockQueryWaitTime, WaitIndex: v.lastIndex, - VaultGrace: v.vaultGrace, }) if err != nil { if err == dep.ErrStopped { diff --git a/vendor/github.com/hashicorp/consul-template/watch/watcher.go b/vendor/github.com/hashicorp/consul-template/watch/watcher.go index fcbaa35217..805740ba5e 100644 --- a/vendor/github.com/hashicorp/consul-template/watch/watcher.go +++ b/vendor/github.com/hashicorp/consul-template/watch/watcher.go @@ -27,6 +27,9 @@ type Watcher struct { // errCh is the chan where any errors will be published. errCh chan error + // blockQueryWaitTime is amount of time in seconds to do a blocking query for + blockQueryWaitTime time.Duration + // depViewMap is a map of Templates to Views. Templates are keyed by // their string. depViewMap map[string]*View @@ -42,11 +45,6 @@ type Watcher struct { retryFuncConsul RetryFunc retryFuncDefault RetryFunc retryFuncVault RetryFunc - - // vaultGrace is the grace period between a lease and the max TTL for which - // Consul Template will generate a new secret instead of renewing an existing - // one. - vaultGrace time.Duration } type NewWatcherInput struct { @@ -59,6 +57,9 @@ type NewWatcherInput struct { // Once specifies this watcher should tell views to poll exactly once. Once bool + // WaitTime is amount of time in seconds to do a blocking query for + BlockQueryWaitTime time.Duration + // RenewVault indicates if this watcher should renew Vault tokens. RenewVault bool @@ -72,26 +73,21 @@ type NewWatcherInput struct { RetryFuncConsul RetryFunc RetryFuncDefault RetryFunc RetryFuncVault RetryFunc - - // VaultGrace is the grace period between a lease and the max TTL for which - // Consul Template will generate a new secret instead of renewing an existing - // one. - VaultGrace time.Duration } // NewWatcher creates a new watcher using the given API client. func NewWatcher(i *NewWatcherInput) (*Watcher, error) { w := &Watcher{ - clients: i.Clients, - depViewMap: make(map[string]*View), - dataCh: make(chan *View, dataBufferSize), - errCh: make(chan error), - maxStale: i.MaxStale, - once: i.Once, - retryFuncConsul: i.RetryFuncConsul, - retryFuncDefault: i.RetryFuncDefault, - retryFuncVault: i.RetryFuncVault, - vaultGrace: i.VaultGrace, + clients: i.Clients, + depViewMap: make(map[string]*View), + dataCh: make(chan *View, dataBufferSize), + errCh: make(chan error), + maxStale: i.MaxStale, + once: i.Once, + blockQueryWaitTime: i.BlockQueryWaitTime, + retryFuncConsul: i.RetryFuncConsul, + retryFuncDefault: i.RetryFuncDefault, + retryFuncVault: i.RetryFuncVault, } // Start a watcher for the Vault renew if that config was specified @@ -160,12 +156,12 @@ func (w *Watcher) Add(d dep.Dependency) (bool, error) { } v, err := NewView(&NewViewInput{ - Dependency: d, - Clients: w.clients, - MaxStale: w.maxStale, - Once: w.once, - RetryFunc: retryFunc, - VaultGrace: w.vaultGrace, + Dependency: d, + Clients: w.clients, + MaxStale: w.maxStale, + BlockQueryWaitTime: w.blockQueryWaitTime, + Once: w.once, + RetryFunc: retryFunc, }) if err != nil { return false, errors.Wrap(err, "watcher") diff --git a/vendor/github.com/hashicorp/consul/api/agent.go b/vendor/github.com/hashicorp/consul/api/agent.go index 6f8bed092d..929d3ccd34 100644 --- a/vendor/github.com/hashicorp/consul/api/agent.go +++ b/vendor/github.com/hashicorp/consul/api/agent.go @@ -159,6 +159,14 @@ type AgentServiceRegistration struct { Namespace string `json:",omitempty" bexpr:"-" hash:"ignore"` } +//ServiceRegisterOpts is used to pass extra options to the service register. +type ServiceRegisterOpts struct { + //Missing healthchecks will be deleted from the agent. + //Using this parameter allows to idempotently register a service and its checks without + //having to manually deregister checks. + ReplaceExistingChecks bool +} + // AgentCheckRegistration is used to register a new check type AgentCheckRegistration struct { ID string `json:",omitempty"` @@ -182,6 +190,7 @@ type AgentServiceCheck struct { HTTP string `json:",omitempty"` Header map[string][]string `json:",omitempty"` Method string `json:",omitempty"` + Body string `json:",omitempty"` TCP string `json:",omitempty"` Status string `json:",omitempty"` Notes string `json:",omitempty"` @@ -554,8 +563,25 @@ func (a *Agent) MembersOpts(opts MembersOpts) ([]*AgentMember, error) { // ServiceRegister is used to register a new service with // the local agent func (a *Agent) ServiceRegister(service *AgentServiceRegistration) error { + opts := ServiceRegisterOpts{ + ReplaceExistingChecks: false, + } + + return a.serviceRegister(service, opts) +} + +// ServiceRegister is used to register a new service with +// the local agent and can be passed additional options. +func (a *Agent) ServiceRegisterOpts(service *AgentServiceRegistration, opts ServiceRegisterOpts) error { + return a.serviceRegister(service, opts) +} + +func (a *Agent) serviceRegister(service *AgentServiceRegistration, opts ServiceRegisterOpts) error { r := a.c.newRequest("PUT", "/v1/agent/service/register") r.obj = service + if opts.ReplaceExistingChecks { + r.params.Set("replace-existing-checks", "true") + } _, resp, err := requireOK(a.c.doRequest(r)) if err != nil { return err @@ -870,20 +896,29 @@ func (a *Agent) DisableNodeMaintenance() error { // log stream. An empty string will be sent down the given channel when there's // nothing left to stream, after which the caller should close the stopCh. func (a *Agent) Monitor(loglevel string, stopCh <-chan struct{}, q *QueryOptions) (chan string, error) { + return a.monitor(loglevel, false, stopCh, q) +} + +// MonitorJSON is like Monitor except it returns logs in JSON format. +func (a *Agent) MonitorJSON(loglevel string, stopCh <-chan struct{}, q *QueryOptions) (chan string, error) { + return a.monitor(loglevel, true, stopCh, q) +} +func (a *Agent) monitor(loglevel string, logJSON bool, stopCh <-chan struct{}, q *QueryOptions) (chan string, error) { r := a.c.newRequest("GET", "/v1/agent/monitor") r.setQueryOptions(q) if loglevel != "" { r.params.Add("loglevel", loglevel) } + if logJSON { + r.params.Set("logjson", "true") + } _, resp, err := requireOK(a.c.doRequest(r)) if err != nil { return nil, err } - logCh := make(chan string, 64) go func() { defer resp.Body.Close() - scanner := bufio.NewScanner(resp.Body) for { select { @@ -907,7 +942,6 @@ func (a *Agent) Monitor(loglevel string, stopCh <-chan struct{}, q *QueryOptions } } }() - return logCh, nil } diff --git a/vendor/github.com/hashicorp/consul/api/api.go b/vendor/github.com/hashicorp/consul/api/api.go index 05a5e8c3ad..a42a110bce 100644 --- a/vendor/github.com/hashicorp/consul/api/api.go +++ b/vendor/github.com/hashicorp/consul/api/api.go @@ -8,7 +8,6 @@ import ( "fmt" "io" "io/ioutil" - "log" "net" "net/http" "net/url" @@ -18,6 +17,7 @@ import ( "time" "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-rootcerts" ) @@ -358,7 +358,14 @@ type TLSConfig struct { // is not recommended, then you may notice idle connections building up over // time. To avoid this, use the DefaultNonPooledConfig() instead. func DefaultConfig() *Config { - return defaultConfig(cleanhttp.DefaultPooledTransport) + return defaultConfig(nil, cleanhttp.DefaultPooledTransport) +} + +// DefaultConfigWithLogger returns a default configuration for the client. It +// is exactly the same as DefaultConfig, but allows for a pre-configured logger +// object to be passed through. +func DefaultConfigWithLogger(logger hclog.Logger) *Config { + return defaultConfig(logger, cleanhttp.DefaultPooledTransport) } // DefaultNonPooledConfig returns a default configuration for the client which @@ -367,12 +374,18 @@ func DefaultConfig() *Config { // accumulation of idle connections if you make many client objects during the // lifetime of your application. func DefaultNonPooledConfig() *Config { - return defaultConfig(cleanhttp.DefaultTransport) + return defaultConfig(nil, cleanhttp.DefaultTransport) } // defaultConfig returns the default configuration for the client, using the // given function to make the transport. -func defaultConfig(transportFn func() *http.Transport) *Config { +func defaultConfig(logger hclog.Logger, transportFn func() *http.Transport) *Config { + if logger == nil { + logger = hclog.New(&hclog.LoggerOptions{ + Name: "consul-api", + }) + } + config := &Config{ Address: "127.0.0.1:8500", Scheme: "http", @@ -410,7 +423,7 @@ func defaultConfig(transportFn func() *http.Transport) *Config { if ssl := os.Getenv(HTTPSSLEnvName); ssl != "" { enabled, err := strconv.ParseBool(ssl) if err != nil { - log.Printf("[WARN] client: could not parse %s: %s", HTTPSSLEnvName, err) + logger.Warn(fmt.Sprintf("could not parse %s", HTTPSSLEnvName), "error", err) } if enabled { @@ -436,7 +449,7 @@ func defaultConfig(transportFn func() *http.Transport) *Config { if v := os.Getenv(HTTPSSLVerifyEnvName); v != "" { doVerify, err := strconv.ParseBool(v) if err != nil { - log.Printf("[WARN] client: could not parse %s: %s", HTTPSSLVerifyEnvName, err) + logger.Warn(fmt.Sprintf("could not parse %s", HTTPSSLVerifyEnvName), "error", err) } if !doVerify { config.TLSConfig.InsecureSkipVerify = true diff --git a/vendor/github.com/hashicorp/consul/api/discovery_chain.go b/vendor/github.com/hashicorp/consul/api/discovery_chain.go index 407a3b08e3..75fdbaee25 100644 --- a/vendor/github.com/hashicorp/consul/api/discovery_chain.go +++ b/vendor/github.com/hashicorp/consul/api/discovery_chain.go @@ -33,7 +33,6 @@ func (d *DiscoveryChain) Get(name string, opts *DiscoveryChainOptions, q *QueryO if opts.EvaluateInDatacenter != "" { r.params.Set("compile-dc", opts.EvaluateInDatacenter) } - // TODO(namespaces): handle possible EvaluateInNamespace here } if method == "POST" { diff --git a/vendor/github.com/hashicorp/consul/api/go.mod b/vendor/github.com/hashicorp/consul/api/go.mod index c509531731..7770aae90d 100644 --- a/vendor/github.com/hashicorp/consul/api/go.mod +++ b/vendor/github.com/hashicorp/consul/api/go.mod @@ -5,11 +5,12 @@ go 1.12 replace github.com/hashicorp/consul/sdk => ../sdk require ( - github.com/hashicorp/consul/sdk v0.2.0 + github.com/hashicorp/consul/sdk v0.4.0 github.com/hashicorp/go-cleanhttp v0.5.1 + github.com/hashicorp/go-hclog v0.12.0 github.com/hashicorp/go-rootcerts v1.0.2 github.com/hashicorp/go-uuid v1.0.1 github.com/hashicorp/serf v0.8.2 github.com/mitchellh/mapstructure v1.1.2 - github.com/stretchr/testify v1.3.0 + github.com/stretchr/testify v1.4.0 ) diff --git a/vendor/github.com/hashicorp/consul/api/go.sum b/vendor/github.com/hashicorp/consul/api/go.sum index f6a1f9aaf8..40f6fdc743 100644 --- a/vendor/github.com/hashicorp/consul/api/go.sum +++ b/vendor/github.com/hashicorp/consul/api/go.sum @@ -6,21 +6,26 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/hashicorp/consul/sdk v0.4.0 h1:zBtCfKJZcJDBvSCkQJch4ulp59m1rATFLKwNo/LYY30= +github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= 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-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= 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-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= @@ -38,13 +43,24 @@ github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG67 github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= @@ -68,6 +84,8 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -78,5 +96,18 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5 h1:x6r4Jo0KNzOOzYd8lbcRsqjuqEASK6ob3auvWYM4/8U= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd h1:3x5uuvBgE6oaXJjCOvpCC1IpgJogqQ+PqGGU3ZxAgII= -golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9 h1:1/DFK4b7JH8DmkqhUk48onnSfrPzImPoVxuomtbT2nk= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/hashicorp/consul/api/health.go b/vendor/github.com/hashicorp/consul/api/health.go index 1d00701824..2f4894ae6e 100644 --- a/vendor/github.com/hashicorp/consul/api/health.go +++ b/vendor/github.com/hashicorp/consul/api/health.go @@ -51,6 +51,7 @@ type HealthCheckDefinition struct { HTTP string Header map[string][]string Method string + Body string TLSSkipVerify bool TCP string IntervalDuration time.Duration `json:"-"` diff --git a/vendor/github.com/hashicorp/consul/api/prepared_query.go b/vendor/github.com/hashicorp/consul/api/prepared_query.go index 0204581168..5ac2535c71 100644 --- a/vendor/github.com/hashicorp/consul/api/prepared_query.go +++ b/vendor/github.com/hashicorp/consul/api/prepared_query.go @@ -25,6 +25,9 @@ type ServiceQuery struct { // Service is the service to query. Service string + // Namespace of the service to query + Namespace string `json:",omitempty"` + // Near allows baking in the name of a node to automatically distance- // sort from. The magic "_agent" value is supported, which sorts near // the agent which initiated the request by default. @@ -119,6 +122,9 @@ type PreparedQueryExecuteResponse struct { // Service is the service that was queried. Service string + // Namespace of the service that was queried + Namespace string `json:",omitempty"` + // Nodes has the nodes that were output by the query. Nodes []ServiceEntry diff --git a/vendor/github.com/hashicorp/consul/api/txn.go b/vendor/github.com/hashicorp/consul/api/txn.go index 7e756dff40..ef06bcbfef 100644 --- a/vendor/github.com/hashicorp/consul/api/txn.go +++ b/vendor/github.com/hashicorp/consul/api/txn.go @@ -75,12 +75,13 @@ const ( // KVTxnOp defines a single operation inside a transaction. type KVTxnOp struct { - Verb KVOp - Key string - Value []byte - Flags uint64 - Index uint64 - Session string + Verb KVOp + Key string + Value []byte + Flags uint64 + Index uint64 + Session string + Namespace string `json:",omitempty"` } // KVTxnOps defines a set of operations to be performed inside a single diff --git a/vendor/github.com/hashicorp/vault/api/go.sum b/vendor/github.com/hashicorp/vault/api/go.sum index 56fb281105..172833fa1e 100644 --- a/vendor/github.com/hashicorp/vault/api/go.sum +++ b/vendor/github.com/hashicorp/vault/api/go.sum @@ -2,9 +2,11 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= @@ -65,6 +67,7 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -82,6 +85,7 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 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/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= diff --git a/vendor/github.com/hashicorp/vault/api/sys_audit.go b/vendor/github.com/hashicorp/vault/api/sys_audit.go index 2448c0367c..5fa6f3585d 100644 --- a/vendor/github.com/hashicorp/vault/api/sys_audit.go +++ b/vendor/github.com/hashicorp/vault/api/sys_audit.go @@ -116,7 +116,7 @@ func (c *Sys) DisableAudit(path string) error { return err } -// Structures for the requests/resposne are all down here. They aren't +// Structures for the requests/response are all down here. They aren't // individually documented because the map almost directly to the raw HTTP API // documentation. Please refer to that documentation for more details. diff --git a/vendor/github.com/hashicorp/vault/api/sys_monitor.go b/vendor/github.com/hashicorp/vault/api/sys_monitor.go new file mode 100644 index 0000000000..ec27f22855 --- /dev/null +++ b/vendor/github.com/hashicorp/vault/api/sys_monitor.go @@ -0,0 +1,64 @@ +package api + +import ( + "bufio" + "context" + "fmt" +) + +// Monitor returns a channel that outputs strings containing the log messages +// coming from the server. +func (c *Sys) Monitor(ctx context.Context, logLevel string) (chan string, error) { + r := c.c.NewRequest("GET", "/v1/sys/monitor") + + if logLevel == "" { + r.Params.Add("log_level", "info") + } else { + r.Params.Add("log_level", logLevel) + } + + resp, err := c.c.RawRequestWithContext(ctx, r) + if err != nil { + return nil, err + } + + logCh := make(chan string, 64) + + go func() { + scanner := bufio.NewScanner(resp.Body) + droppedCount := 0 + + defer close(logCh) + defer resp.Body.Close() + + for { + if ctx.Err() != nil { + return + } + + if !scanner.Scan() { + return + } + + logMessage := scanner.Text() + + if droppedCount > 0 { + select { + case logCh <- fmt.Sprintf("Monitor dropped %d logs during monitor request\n", droppedCount): + droppedCount = 0 + default: + droppedCount++ + continue + } + } + + select { + case logCh <- logMessage: + default: + droppedCount++ + } + } + }() + + return logCh, nil +} diff --git a/vendor/github.com/hashicorp/vault/sdk/helper/ldaputil/client.go b/vendor/github.com/hashicorp/vault/sdk/helper/ldaputil/client.go index 445953edf4..886cc72cb8 100644 --- a/vendor/github.com/hashicorp/vault/sdk/helper/ldaputil/client.go +++ b/vendor/github.com/hashicorp/vault/sdk/helper/ldaputil/client.go @@ -171,10 +171,9 @@ func (c *Client) GetUserDN(cfg *ConfigEntry, conn Connection, bindDN, username s if err != nil { return userDN, errwrap.Wrapf("LDAP search failed for detecting user: {{err}}", err) } - if len(result.Entries) != 1 { - return userDN, fmt.Errorf("LDAP search for userdn 0 or not unique") + for _, e := range result.Entries { + userDN = e.DN } - userDN = result.Entries[0].DN } else { userDN = bindDN } diff --git a/vendor/github.com/hashicorp/vault/sdk/logical/response.go b/vendor/github.com/hashicorp/vault/sdk/logical/response.go index fb799ba4b8..bc7b235219 100644 --- a/vendor/github.com/hashicorp/vault/sdk/logical/response.go +++ b/vendor/github.com/hashicorp/vault/sdk/logical/response.go @@ -185,13 +185,13 @@ func RespondWithStatusCode(resp *Response, req *Request, code int) (*Response, e } // HTTPResponseWriter is optionally added to a request object and can be used to -// write directly to the HTTP response writter. +// write directly to the HTTP response writer. type HTTPResponseWriter struct { http.ResponseWriter written *uint32 } -// NewHTTPResponseWriter creates a new HTTPRepoinseWriter object that wraps the +// NewHTTPResponseWriter creates a new HTTPResponseWriter object that wraps the // provided io.Writer. func NewHTTPResponseWriter(w http.ResponseWriter) *HTTPResponseWriter { return &HTTPResponseWriter{ diff --git a/vendor/github.com/kr/pretty/License b/vendor/github.com/kr/pretty/License index 05c783ccf6..480a328059 100644 --- a/vendor/github.com/kr/pretty/License +++ b/vendor/github.com/kr/pretty/License @@ -1,5 +1,3 @@ -The MIT License (MIT) - Copyright 2012 Keith Rarick Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/vendor/github.com/kr/pretty/formatter.go b/vendor/github.com/kr/pretty/formatter.go index a317d7b8ee..df61d8d19e 100644 --- a/vendor/github.com/kr/pretty/formatter.go +++ b/vendor/github.com/kr/pretty/formatter.go @@ -125,7 +125,6 @@ func (p *printer) printValue(v reflect.Value, showType, quote bool) { } keys := v.MapKeys() for i := 0; i < v.Len(); i++ { - showTypeInStruct := true k := keys[i] mv := v.MapIndex(k) pp.printValue(k, false, true) @@ -133,7 +132,7 @@ func (p *printer) printValue(v reflect.Value, showType, quote bool) { if expand { writeByte(pp, '\t') } - showTypeInStruct = t.Elem().Kind() == reflect.Interface + showTypeInStruct := t.Elem().Kind() == reflect.Interface pp.printValue(mv, showTypeInStruct, true) if expand { io.WriteString(pp, ",\n") diff --git a/vendor/github.com/kr/pretty/go.mod b/vendor/github.com/kr/pretty/go.mod index 1e29533143..9a27b6e964 100644 --- a/vendor/github.com/kr/pretty/go.mod +++ b/vendor/github.com/kr/pretty/go.mod @@ -1,3 +1,5 @@ -module "github.com/kr/pretty" +module github.com/kr/pretty -require "github.com/kr/text" v0.1.0 +go 1.12 + +require github.com/kr/text v0.1.0 diff --git a/vendor/github.com/kr/pretty/go.sum b/vendor/github.com/kr/pretty/go.sum new file mode 100644 index 0000000000..714f82a201 --- /dev/null +++ b/vendor/github.com/kr/pretty/go.sum @@ -0,0 +1,3 @@ +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= diff --git a/vendor/github.com/kr/pretty/pretty.go b/vendor/github.com/kr/pretty/pretty.go index 49423ec7f5..b4ca583c02 100644 --- a/vendor/github.com/kr/pretty/pretty.go +++ b/vendor/github.com/kr/pretty/pretty.go @@ -75,7 +75,7 @@ func Printf(format string, a ...interface{}) (n int, errno error) { // Println pretty-prints its operands and writes to standard output. // -// Calling Print(x, y) is equivalent to +// Calling Println(x, y) is equivalent to // fmt.Println(Formatter(x), Formatter(y)), but each operand is // formatted with "%# v". func Println(a ...interface{}) (n int, errno error) { diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml index 98db8f060b..7942c565ce 100644 --- a/vendor/github.com/mattn/go-colorable/.travis.yml +++ b/vendor/github.com/mattn/go-colorable/.travis.yml @@ -1,9 +1,15 @@ language: go +sudo: false go: + - 1.13.x - tip before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover + - go get -t -v ./... + script: - - $HOME/gopath/bin/goveralls -repotoken xnXqRGwgW3SXIguzxf90ZSK1GPYZPaGrw + - ./go.test.sh + +after_success: + - bash <(curl -s https://codecov.io/bash) + diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md index 56729a92ca..e055952b66 100644 --- a/vendor/github.com/mattn/go-colorable/README.md +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -1,8 +1,8 @@ # go-colorable -[![Godoc Reference](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) [![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) -[![Coverage Status](https://coveralls.io/repos/github/mattn/go-colorable/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-colorable?branch=master) +[![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable) +[![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) [![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) Colorable writer for windows. diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go index 0b0aef8370..1f7806fe16 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_appengine.go +++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go @@ -27,3 +27,11 @@ func NewColorableStdout() io.Writer { func NewColorableStderr() io.Writer { return os.Stderr } + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go index 3fb771dcca..08cbd1e0fa 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_others.go +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -28,3 +28,11 @@ func NewColorableStdout() io.Writer { func NewColorableStderr() io.Writer { return os.Stderr } + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go index 1bd628f25c..b9e936344c 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -27,6 +27,8 @@ const ( backgroundRed = 0x40 backgroundIntensity = 0x80 backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) + + cENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4 ) const ( @@ -78,6 +80,8 @@ var ( procGetConsoleCursorInfo = kernel32.NewProc("GetConsoleCursorInfo") procSetConsoleCursorInfo = kernel32.NewProc("SetConsoleCursorInfo") procSetConsoleTitle = kernel32.NewProc("SetConsoleTitleW") + procGetConsoleMode = kernel32.NewProc("GetConsoleMode") + procSetConsoleMode = kernel32.NewProc("SetConsoleMode") procCreateConsoleScreenBuffer = kernel32.NewProc("CreateConsoleScreenBuffer") ) @@ -98,6 +102,10 @@ func NewColorable(file *os.File) io.Writer { } if isatty.IsTerminal(file.Fd()) { + var mode uint32 + if r, _, _ := procGetConsoleMode.Call(file.Fd(), uintptr(unsafe.Pointer(&mode))); r != 0 && mode&cENABLE_VIRTUAL_TERMINAL_PROCESSING != 0 { + return file + } var csbi consoleScreenBufferInfo handle := syscall.Handle(file.Fd()) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) @@ -1003,3 +1011,23 @@ func n256setup() { n256backAttr[i] = c.backgroundAttr() } } + +// EnableColorsStdout enable colors if possible. +func EnableColorsStdout(enabled *bool) func() { + var mode uint32 + h := os.Stdout.Fd() + if r, _, _ := procGetConsoleMode.Call(h, uintptr(unsafe.Pointer(&mode))); r != 0 { + if r, _, _ = procSetConsoleMode.Call(h, uintptr(mode|cENABLE_VIRTUAL_TERMINAL_PROCESSING)); r != 0 { + if enabled != nil { + *enabled = true + } + return func() { + procSetConsoleMode.Call(h, uintptr(mode)) + } + } + } + if enabled != nil { + *enabled = true + } + return func() {} +} diff --git a/vendor/github.com/mattn/go-colorable/go.mod b/vendor/github.com/mattn/go-colorable/go.mod index ef3ca9d4c3..1e590b8199 100644 --- a/vendor/github.com/mattn/go-colorable/go.mod +++ b/vendor/github.com/mattn/go-colorable/go.mod @@ -1,3 +1,8 @@ module github.com/mattn/go-colorable -require github.com/mattn/go-isatty v0.0.8 +require ( + github.com/mattn/go-isatty v0.0.12 + golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae // indirect +) + +go 1.13 diff --git a/vendor/github.com/mattn/go-colorable/go.sum b/vendor/github.com/mattn/go-colorable/go.sum index 2c12960ec7..cf5b95d97c 100644 --- a/vendor/github.com/mattn/go-colorable/go.sum +++ b/vendor/github.com/mattn/go-colorable/go.sum @@ -1,4 +1,5 @@ -github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/mattn/go-colorable/go.test.sh b/vendor/github.com/mattn/go-colorable/go.test.sh new file mode 100644 index 0000000000..012162b077 --- /dev/null +++ b/vendor/github.com/mattn/go-colorable/go.test.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e +echo "" > coverage.txt + +for d in $(go list ./... | grep -v vendor); do + go test -race -coverprofile=profile.out -covermode=atomic "$d" + if [ -f profile.out ]; then + cat profile.out >> coverage.txt + rm profile.out + fi +done diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml index 5597e026dd..604314dd44 100644 --- a/vendor/github.com/mattn/go-isatty/.travis.yml +++ b/vendor/github.com/mattn/go-isatty/.travis.yml @@ -1,13 +1,14 @@ language: go +sudo: false go: + - 1.13.x - tip -os: - - linux - - osx - before_install: - - go get github.com/mattn/goveralls - - go get golang.org/x/tools/cmd/cover + - go get -t -v ./... + script: - - $HOME/gopath/bin/goveralls -repotoken 3gHdORO5k5ziZcWMBxnd9LrMZaJs8m9x5 + - ./go.test.sh + +after_success: + - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/mattn/go-isatty/README.md b/vendor/github.com/mattn/go-isatty/README.md index 1e69004bb0..38418353e3 100644 --- a/vendor/github.com/mattn/go-isatty/README.md +++ b/vendor/github.com/mattn/go-isatty/README.md @@ -1,7 +1,7 @@ # go-isatty [![Godoc Reference](https://godoc.org/github.com/mattn/go-isatty?status.svg)](http://godoc.org/github.com/mattn/go-isatty) -[![Build Status](https://travis-ci.org/mattn/go-isatty.svg?branch=master)](https://travis-ci.org/mattn/go-isatty) +[![Codecov](https://codecov.io/gh/mattn/go-isatty/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-isatty) [![Coverage Status](https://coveralls.io/repos/github/mattn/go-isatty/badge.svg?branch=master)](https://coveralls.io/github/mattn/go-isatty?branch=master) [![Go Report Card](https://goreportcard.com/badge/mattn/go-isatty)](https://goreportcard.com/report/mattn/go-isatty) diff --git a/vendor/github.com/mattn/go-isatty/go.mod b/vendor/github.com/mattn/go-isatty/go.mod index a8ddf404fc..605c4c2210 100644 --- a/vendor/github.com/mattn/go-isatty/go.mod +++ b/vendor/github.com/mattn/go-isatty/go.mod @@ -1,5 +1,5 @@ module github.com/mattn/go-isatty -require golang.org/x/sys v0.0.0-20191008105621-543471e840be +go 1.12 -go 1.14 +require golang.org/x/sys v0.0.0-20200116001909-b77594299b42 diff --git a/vendor/github.com/mattn/go-isatty/go.sum b/vendor/github.com/mattn/go-isatty/go.sum index c141fc53a9..912e29cbc1 100644 --- a/vendor/github.com/mattn/go-isatty/go.sum +++ b/vendor/github.com/mattn/go-isatty/go.sum @@ -1,4 +1,2 @@ -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/mattn/go-isatty/go.test.sh b/vendor/github.com/mattn/go-isatty/go.test.sh new file mode 100644 index 0000000000..012162b077 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/go.test.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +set -e +echo "" > coverage.txt + +for d in $(go list ./... | grep -v vendor); do + go test -race -coverprofile=profile.out -covermode=atomic "$d" + if [ -f profile.out ]; then + cat profile.out >> coverage.txt + rm profile.out + fi +done diff --git a/vendor/github.com/mattn/go-isatty/isatty_android.go b/vendor/github.com/mattn/go-isatty/isatty_android.go deleted file mode 100644 index d3567cb5bf..0000000000 --- a/vendor/github.com/mattn/go-isatty/isatty_android.go +++ /dev/null @@ -1,23 +0,0 @@ -// +build android - -package isatty - -import ( - "syscall" - "unsafe" -) - -const ioctlReadTermios = syscall.TCGETS - -// IsTerminal return true if the file descriptor is terminal. -func IsTerminal(fd uintptr) bool { - var termios syscall.Termios - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) - return err == 0 -} - -// IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 -// terminal. This is also always false on this environment. -func IsCygwinTerminal(fd uintptr) bool { - return false -} diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go index 07e93039db..711f288085 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -3,18 +3,12 @@ package isatty -import ( - "syscall" - "unsafe" -) - -const ioctlReadTermios = syscall.TIOCGETA +import "golang.org/x/sys/unix" // IsTerminal return true if the file descriptor is terminal. func IsTerminal(fd uintptr) bool { - var termios syscall.Termios - _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, ioctlReadTermios, uintptr(unsafe.Pointer(&termios)), 0, 0, 0) - return err == 0 + _, err := unix.IoctlGetTermios(int(fd), unix.TIOCGETA) + return err == nil } // IsCygwinTerminal return true if the file descriptor is a cygwin or msys2 diff --git a/vendor/github.com/mattn/go-isatty/isatty_plan9.go b/vendor/github.com/mattn/go-isatty/isatty_plan9.go index bc0a70920f..c5b6e0c084 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_plan9.go +++ b/vendor/github.com/mattn/go-isatty/isatty_plan9.go @@ -8,7 +8,7 @@ import ( // IsTerminal returns true if the given file descriptor is a terminal. func IsTerminal(fd uintptr) bool { - path, err := syscall.Fd2path(fd) + path, err := syscall.Fd2path(int(fd)) if err != nil { return false } diff --git a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go index 453b025d0d..31a1ca973c 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go +++ b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go @@ -1,6 +1,5 @@ // +build linux aix // +build !appengine -// +build !android package isatty diff --git a/vendor/github.com/mattn/go-isatty/renovate.json b/vendor/github.com/mattn/go-isatty/renovate.json new file mode 100644 index 0000000000..5ae9d96b74 --- /dev/null +++ b/vendor/github.com/mattn/go-isatty/renovate.json @@ -0,0 +1,8 @@ +{ + "extends": [ + "config:base" + ], + "postUpdateOptions": [ + "gomodTidy" + ] +} diff --git a/vendor/gopkg.in/yaml.v2/.travis.yml b/vendor/gopkg.in/yaml.v2/.travis.yml index 9f556934d8..055480b9ef 100644 --- a/vendor/gopkg.in/yaml.v2/.travis.yml +++ b/vendor/gopkg.in/yaml.v2/.travis.yml @@ -1,12 +1,16 @@ language: go go: - - 1.4 - - 1.5 - - 1.6 - - 1.7 - - 1.8 - - 1.9 - - tip + - "1.4.x" + - "1.5.x" + - "1.6.x" + - "1.7.x" + - "1.8.x" + - "1.9.x" + - "1.10.x" + - "1.11.x" + - "1.12.x" + - "1.13.x" + - "tip" go_import_path: gopkg.in/yaml.v2 diff --git a/vendor/gopkg.in/yaml.v2/scannerc.go b/vendor/gopkg.in/yaml.v2/scannerc.go index 570b8ecd10..0b9bb6030a 100644 --- a/vendor/gopkg.in/yaml.v2/scannerc.go +++ b/vendor/gopkg.in/yaml.v2/scannerc.go @@ -626,30 +626,17 @@ func trace(args ...interface{}) func() { func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { // While we need more tokens to fetch, do it. for { - // Check if we really need to fetch more tokens. - need_more_tokens := false - - if parser.tokens_head == len(parser.tokens) { - // Queue is empty. - need_more_tokens = true - } else { - // Check if any potential simple key may occupy the head position. - if !yaml_parser_stale_simple_keys(parser) { + if parser.tokens_head != len(parser.tokens) { + // If queue is non-empty, check if any potential simple key may + // occupy the head position. + head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed] + if !ok { + break + } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok { return false + } else if !valid { + break } - - for i := range parser.simple_keys { - simple_key := &parser.simple_keys[i] - if simple_key.possible && simple_key.token_number == parser.tokens_parsed { - need_more_tokens = true - break - } - } - } - - // We are finished. - if !need_more_tokens { - break } // Fetch the next token. if !yaml_parser_fetch_next_token(parser) { @@ -678,11 +665,6 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { return false } - // Remove obsolete potential simple keys. - if !yaml_parser_stale_simple_keys(parser) { - return false - } - // Check the indentation level against the current column. if !yaml_parser_unroll_indent(parser, parser.mark.column) { return false @@ -837,29 +819,30 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool { "found character that cannot start any token") } -// Check the list of potential simple keys and remove the positions that -// cannot contain simple keys anymore. -func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool { - // Check for a potential simple key for each flow level. - for i := range parser.simple_keys { - simple_key := &parser.simple_keys[i] - - // The specification requires that a simple key - // - // - is limited to a single line, - // - is shorter than 1024 characters. - if simple_key.possible && (simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index) { - - // Check if the potential simple key to be removed is required. - if simple_key.required { - return yaml_parser_set_scanner_error(parser, - "while scanning a simple key", simple_key.mark, - "could not find expected ':'") - } - simple_key.possible = false - } +func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) { + if !simple_key.possible { + return false, true } - return true + + // The 1.2 specification says: + // + // "If the ? indicator is omitted, parsing needs to see past the + // implicit key to recognize it as such. To limit the amount of + // lookahead required, the “:” indicator must appear at most 1024 + // Unicode characters beyond the start of the key. In addition, the key + // is restricted to a single line." + // + if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index { + // Check if the potential simple key to be removed is required. + if simple_key.required { + return false, yaml_parser_set_scanner_error(parser, + "while scanning a simple key", simple_key.mark, + "could not find expected ':'") + } + simple_key.possible = false + return false, true + } + return true, true } // Check if a simple key may start at the current position and add it if @@ -879,13 +862,14 @@ func yaml_parser_save_simple_key(parser *yaml_parser_t) bool { possible: true, required: required, token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, } - simple_key.mark = parser.mark if !yaml_parser_remove_simple_key(parser) { return false } parser.simple_keys[len(parser.simple_keys)-1] = simple_key + parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1 } return true } @@ -900,9 +884,10 @@ func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool { "while scanning a simple key", parser.simple_keys[i].mark, "could not find expected ':'") } + // Remove the key from the stack. + parser.simple_keys[i].possible = false + delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number) } - // Remove the key from the stack. - parser.simple_keys[i].possible = false return true } @@ -912,7 +897,12 @@ const max_flow_level = 10000 // Increase the flow level and resize the simple key list if needed. func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { // Reset the simple key on the next level. - parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{ + possible: false, + required: false, + token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), + mark: parser.mark, + }) // Increase the flow level. parser.flow_level++ @@ -928,7 +918,9 @@ func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { if parser.flow_level > 0 { parser.flow_level-- - parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1] + last := len(parser.simple_keys) - 1 + delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number) + parser.simple_keys = parser.simple_keys[:last] } return true } @@ -1005,6 +997,8 @@ func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool { // Initialize the simple key stack. parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) + parser.simple_keys_by_tok = make(map[int]int) + // A simple key is allowed at the beginning of the stream. parser.simple_key_allowed = true @@ -1286,7 +1280,11 @@ func yaml_parser_fetch_value(parser *yaml_parser_t) bool { simple_key := &parser.simple_keys[len(parser.simple_keys)-1] // Have we found a simple key? - if simple_key.possible { + if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok { + return false + + } else if valid { + // Create the KEY token and insert it into the queue. token := yaml_token_t{ typ: yaml_KEY_TOKEN, @@ -1304,6 +1302,7 @@ func yaml_parser_fetch_value(parser *yaml_parser_t) bool { // Remove the simple key. simple_key.possible = false + delete(parser.simple_keys_by_tok, simple_key.token_number) // A simple key cannot follow another simple key. parser.simple_key_allowed = false diff --git a/vendor/gopkg.in/yaml.v2/yaml.go b/vendor/gopkg.in/yaml.v2/yaml.go index de85aa4cdb..89650e293a 100644 --- a/vendor/gopkg.in/yaml.v2/yaml.go +++ b/vendor/gopkg.in/yaml.v2/yaml.go @@ -89,7 +89,7 @@ func UnmarshalStrict(in []byte, out interface{}) (err error) { return unmarshal(in, out, true) } -// A Decorder reads and decodes YAML values from an input stream. +// A Decoder reads and decodes YAML values from an input stream. type Decoder struct { strict bool parser *parser diff --git a/vendor/gopkg.in/yaml.v2/yamlh.go b/vendor/gopkg.in/yaml.v2/yamlh.go index e25cee563b..f6a9c8e34b 100644 --- a/vendor/gopkg.in/yaml.v2/yamlh.go +++ b/vendor/gopkg.in/yaml.v2/yamlh.go @@ -579,6 +579,7 @@ type yaml_parser_t struct { simple_key_allowed bool // May a simple key occur at the current position? simple_keys []yaml_simple_key_t // The stack of simple keys. + simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number // Parser stuff diff --git a/vendor/modules.txt b/vendor/modules.txt index 0cc436e25a..f4f079e286 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -233,7 +233,7 @@ github.com/duosecurity/duo_api_golang github.com/duosecurity/duo_api_golang/authapi # github.com/elazarl/go-bindata-assetfs v1.0.1-0.20200509193318-234c15e7648f github.com/elazarl/go-bindata-assetfs -# github.com/fatih/color v1.7.0 +# github.com/fatih/color v1.9.0 github.com/fatih/color # github.com/fatih/structs v1.1.0 github.com/fatih/structs @@ -313,7 +313,7 @@ github.com/gorhill/cronexpr github.com/gorilla/websocket # github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed github.com/hailocab/go-hostpool -# github.com/hashicorp/consul-template v0.22.0 +# github.com/hashicorp/consul-template v0.25.0 github.com/hashicorp/consul-template/child github.com/hashicorp/consul-template/config github.com/hashicorp/consul-template/dependency @@ -324,7 +324,7 @@ github.com/hashicorp/consul-template/signals github.com/hashicorp/consul-template/template github.com/hashicorp/consul-template/version github.com/hashicorp/consul-template/watch -# github.com/hashicorp/consul/api v1.2.1-0.20200128105449-6681be918a6e +# github.com/hashicorp/consul/api v1.4.0 github.com/hashicorp/consul/api # github.com/hashicorp/errwrap v1.0.0 github.com/hashicorp/errwrap @@ -596,7 +596,7 @@ github.com/keybase/go-crypto/openpgp/s2k github.com/keybase/go-crypto/rsa # github.com/konsorten/go-windows-terminal-sequences v1.0.1 github.com/konsorten/go-windows-terminal-sequences -# github.com/kr/pretty v0.1.0 +# github.com/kr/pretty v0.2.0 github.com/kr/pretty # github.com/kr/text v0.1.0 github.com/kr/text @@ -604,9 +604,9 @@ github.com/kr/text github.com/lib/pq github.com/lib/pq/oid github.com/lib/pq/scram -# github.com/mattn/go-colorable v0.1.4 +# github.com/mattn/go-colorable v0.1.6 github.com/mattn/go-colorable -# github.com/mattn/go-isatty v0.0.10 +# github.com/mattn/go-isatty v0.0.12 github.com/mattn/go-isatty # github.com/mattn/go-shellwords v1.0.5 github.com/mattn/go-shellwords @@ -1110,7 +1110,7 @@ gopkg.in/square/go-jose.v2 gopkg.in/square/go-jose.v2/cipher gopkg.in/square/go-jose.v2/json gopkg.in/square/go-jose.v2/jwt -# gopkg.in/yaml.v2 v2.2.5 +# gopkg.in/yaml.v2 v2.2.8 gopkg.in/yaml.v2 # honnef.co/go/tools v0.0.1-2020.1.3 honnef.co/go/tools/arg