mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 02:02:43 +00:00
Add a new "vault monitor" command (#8477)
Add a new "vault monitor" command Co-authored-by: ncabatoff <ncabatoff@hashicorp.com> Co-authored-by: Calvin Leung Huang <cleung2010@gmail.com> Co-authored-by: Jeff Mitchell <jeffrey.mitchell@gmail.com>
This commit is contained in:
@@ -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=
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
64
api/sys_monitor.go
Normal file
64
api/sys_monitor.go
Normal file
@@ -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
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
118
command/monitor.go
Normal file
118
command/monitor.go
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
99
command/monitor_test.go
Normal file
99
command/monitor_test.go
Normal file
@@ -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
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
2
go.mod
2
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
|
||||
|
||||
17
go.sum
17
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=
|
||||
|
||||
166
helper/monitor/monitor.go
Normal file
166
helper/monitor/monitor.go
Normal file
@@ -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
|
||||
}
|
||||
96
helper/monitor/monitor_test.go
Normal file
96
helper/monitor/monitor_test.go
Normal file
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
82
http/sys_monitor_test.go
Normal file
82
http/sys_monitor_test.go
Normal file
@@ -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
|
||||
}
|
||||
@@ -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{
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 /<header>
|
||||
Clears the header value for UI.
|
||||
|
||||
|
||||
LIST /
|
||||
List the headers configured for the UI.
|
||||
`,
|
||||
|
||||
@@ -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/?",
|
||||
|
||||
@@ -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
|
||||
|
||||
5
vendor/github.com/fatih/color/.travis.yml
generated
vendored
5
vendor/github.com/fatih/color/.travis.yml
generated
vendored
@@ -1,5 +0,0 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.8.x
|
||||
- tip
|
||||
|
||||
27
vendor/github.com/fatih/color/Gopkg.lock
generated
vendored
27
vendor/github.com/fatih/color/Gopkg.lock
generated
vendored
@@ -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
|
||||
30
vendor/github.com/fatih/color/Gopkg.toml
generated
vendored
30
vendor/github.com/fatih/color/Gopkg.toml
generated
vendored
@@ -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"
|
||||
11
vendor/github.com/fatih/color/README.md
generated
vendored
11
vendor/github.com/fatih/color/README.md
generated
vendored
@@ -1,6 +1,12 @@
|
||||
# Color [](https://godoc.org/github.com/fatih/color) [](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 [](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
|
||||
|
||||
8
vendor/github.com/fatih/color/go.mod
generated
vendored
Normal file
8
vendor/github.com/fatih/color/go.mod
generated
vendored
Normal file
@@ -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
|
||||
)
|
||||
8
vendor/github.com/fatih/color/go.sum
generated
vendored
Normal file
8
vendor/github.com/fatih/color/go.sum
generated
vendored
Normal file
@@ -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=
|
||||
31
vendor/github.com/hashicorp/consul-template/child/child.go
generated
vendored
31
vendor/github.com/hashicorp/consul-template/child/child.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
|
||||
50
vendor/github.com/hashicorp/consul-template/config/config.go
generated
vendored
50
vendor/github.com/hashicorp/consul-template/config/config.go
generated
vendored
@@ -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 {
|
||||
|
||||
16
vendor/github.com/hashicorp/consul-template/config/consul.go
generated
vendored
16
vendor/github.com/hashicorp/consul-template/config/consul.go
generated
vendored
@@ -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,
|
||||
|
||||
22
vendor/github.com/hashicorp/consul-template/config/dedup.go
generated
vendored
22
vendor/github.com/hashicorp/consul-template/config/dedup.go
generated
vendored
@@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
53
vendor/github.com/hashicorp/consul-template/config/default_delimiters.go
generated
vendored
Normal file
53
vendor/github.com/hashicorp/consul-template/config/default_delimiters.go
generated
vendored
Normal file
@@ -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
|
||||
}
|
||||
3
vendor/github.com/hashicorp/consul-template/config/exec.go
generated
vendored
3
vendor/github.com/hashicorp/consul-template/config/exec.go
generated
vendored
@@ -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
|
||||
|
||||
25
vendor/github.com/hashicorp/consul-template/config/syslog.go
generated
vendored
25
vendor/github.com/hashicorp/consul-template/config/syslog.go
generated
vendored
@@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
44
vendor/github.com/hashicorp/consul-template/config/vault.go
generated
vendored
44
vendor/github.com/hashicorp/consul-template/config/vault.go
generated
vendored
@@ -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,
|
||||
|
||||
5
vendor/github.com/hashicorp/consul-template/dependency/client_set.go
generated
vendored
5
vendor/github.com/hashicorp/consul-template/dependency/client_set.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
72
vendor/github.com/hashicorp/consul-template/dependency/connect_ca.go
generated
vendored
Normal file
72
vendor/github.com/hashicorp/consul-template/dependency/connect_ca.go
generated
vendored
Normal file
@@ -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"
|
||||
}
|
||||
77
vendor/github.com/hashicorp/consul-template/dependency/connect_leaf.go
generated
vendored
Normal file
77
vendor/github.com/hashicorp/consul-template/dependency/connect_leaf.go
generated
vendored
Normal file
@@ -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"
|
||||
}
|
||||
41
vendor/github.com/hashicorp/consul-template/dependency/health_service.go
generated
vendored
41
vendor/github.com/hashicorp/consul-template/dependency/health_service.go
generated
vendored
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
27
vendor/github.com/hashicorp/consul-template/dependency/vault_common.go
generated
vendored
27
vendor/github.com/hashicorp/consul-template/dependency/vault_common.go
generated
vendored
@@ -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)
|
||||
|
||||
3
vendor/github.com/hashicorp/consul-template/dependency/vault_read.go
generated
vendored
3
vendor/github.com/hashicorp/consul-template/dependency/vault_read.go
generated
vendored
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
27
vendor/github.com/hashicorp/consul-template/dependency/vault_token.go
generated
vendored
27
vendor/github.com/hashicorp/consul-template/dependency/vault_token.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
|
||||
7
vendor/github.com/hashicorp/consul-template/logging/logging.go
generated
vendored
7
vendor/github.com/hashicorp/consul-template/logging/logging.go
generated
vendored
@@ -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)
|
||||
}
|
||||
|
||||
58
vendor/github.com/hashicorp/consul-template/manager/runner.go
generated
vendored
58
vendor/github.com/hashicorp/consul-template/manager/runner.go
generated
vendored
@@ -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 {
|
||||
|
||||
236
vendor/github.com/hashicorp/consul-template/template/funcs.go
generated
vendored
236
vendor/github.com/hashicorp/consul-template/template/funcs.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
11
vendor/github.com/hashicorp/consul-template/template/template.go
generated
vendored
11
vendor/github.com/hashicorp/consul-template/template/template.go
generated
vendored
@@ -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 {
|
||||
|
||||
2
vendor/github.com/hashicorp/consul-template/version/version.go
generated
vendored
2
vendor/github.com/hashicorp/consul-template/version/version.go
generated
vendored
@@ -2,7 +2,7 @@ package version
|
||||
|
||||
import "fmt"
|
||||
|
||||
const Version = "0.22.0"
|
||||
const Version = "0.25.0"
|
||||
|
||||
var (
|
||||
Name string
|
||||
|
||||
38
vendor/github.com/hashicorp/consul-template/watch/view.go
generated
vendored
38
vendor/github.com/hashicorp/consul-template/watch/view.go
generated
vendored
@@ -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 {
|
||||
|
||||
48
vendor/github.com/hashicorp/consul-template/watch/watcher.go
generated
vendored
48
vendor/github.com/hashicorp/consul-template/watch/watcher.go
generated
vendored
@@ -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")
|
||||
|
||||
40
vendor/github.com/hashicorp/consul/api/agent.go
generated
vendored
40
vendor/github.com/hashicorp/consul/api/agent.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
|
||||
25
vendor/github.com/hashicorp/consul/api/api.go
generated
vendored
25
vendor/github.com/hashicorp/consul/api/api.go
generated
vendored
@@ -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
|
||||
|
||||
1
vendor/github.com/hashicorp/consul/api/discovery_chain.go
generated
vendored
1
vendor/github.com/hashicorp/consul/api/discovery_chain.go
generated
vendored
@@ -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" {
|
||||
|
||||
5
vendor/github.com/hashicorp/consul/api/go.mod
generated
vendored
5
vendor/github.com/hashicorp/consul/api/go.mod
generated
vendored
@@ -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
|
||||
)
|
||||
|
||||
43
vendor/github.com/hashicorp/consul/api/go.sum
generated
vendored
43
vendor/github.com/hashicorp/consul/api/go.sum
generated
vendored
@@ -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=
|
||||
|
||||
1
vendor/github.com/hashicorp/consul/api/health.go
generated
vendored
1
vendor/github.com/hashicorp/consul/api/health.go
generated
vendored
@@ -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:"-"`
|
||||
|
||||
6
vendor/github.com/hashicorp/consul/api/prepared_query.go
generated
vendored
6
vendor/github.com/hashicorp/consul/api/prepared_query.go
generated
vendored
@@ -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
|
||||
|
||||
|
||||
13
vendor/github.com/hashicorp/consul/api/txn.go
generated
vendored
13
vendor/github.com/hashicorp/consul/api/txn.go
generated
vendored
@@ -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
|
||||
|
||||
4
vendor/github.com/hashicorp/vault/api/go.sum
generated
vendored
4
vendor/github.com/hashicorp/vault/api/go.sum
generated
vendored
@@ -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=
|
||||
|
||||
2
vendor/github.com/hashicorp/vault/api/sys_audit.go
generated
vendored
2
vendor/github.com/hashicorp/vault/api/sys_audit.go
generated
vendored
@@ -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.
|
||||
|
||||
|
||||
64
vendor/github.com/hashicorp/vault/api/sys_monitor.go
generated
vendored
Normal file
64
vendor/github.com/hashicorp/vault/api/sys_monitor.go
generated
vendored
Normal file
@@ -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
|
||||
}
|
||||
5
vendor/github.com/hashicorp/vault/sdk/helper/ldaputil/client.go
generated
vendored
5
vendor/github.com/hashicorp/vault/sdk/helper/ldaputil/client.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
4
vendor/github.com/hashicorp/vault/sdk/logical/response.go
generated
vendored
4
vendor/github.com/hashicorp/vault/sdk/logical/response.go
generated
vendored
@@ -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{
|
||||
|
||||
2
vendor/github.com/kr/pretty/License
generated
vendored
2
vendor/github.com/kr/pretty/License
generated
vendored
@@ -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
|
||||
|
||||
3
vendor/github.com/kr/pretty/formatter.go
generated
vendored
3
vendor/github.com/kr/pretty/formatter.go
generated
vendored
@@ -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")
|
||||
|
||||
6
vendor/github.com/kr/pretty/go.mod
generated
vendored
6
vendor/github.com/kr/pretty/go.mod
generated
vendored
@@ -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
|
||||
|
||||
3
vendor/github.com/kr/pretty/go.sum
generated
vendored
Normal file
3
vendor/github.com/kr/pretty/go.sum
generated
vendored
Normal file
@@ -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=
|
||||
2
vendor/github.com/kr/pretty/pretty.go
generated
vendored
2
vendor/github.com/kr/pretty/pretty.go
generated
vendored
@@ -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) {
|
||||
|
||||
12
vendor/github.com/mattn/go-colorable/.travis.yml
generated
vendored
12
vendor/github.com/mattn/go-colorable/.travis.yml
generated
vendored
@@ -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)
|
||||
|
||||
|
||||
4
vendor/github.com/mattn/go-colorable/README.md
generated
vendored
4
vendor/github.com/mattn/go-colorable/README.md
generated
vendored
@@ -1,8 +1,8 @@
|
||||
# go-colorable
|
||||
|
||||
[](http://godoc.org/github.com/mattn/go-colorable)
|
||||
[](https://travis-ci.org/mattn/go-colorable)
|
||||
[](https://coveralls.io/github/mattn/go-colorable?branch=master)
|
||||
[](https://codecov.io/gh/mattn/go-colorable)
|
||||
[](http://godoc.org/github.com/mattn/go-colorable)
|
||||
[](https://goreportcard.com/report/mattn/go-colorable)
|
||||
|
||||
Colorable writer for windows.
|
||||
|
||||
8
vendor/github.com/mattn/go-colorable/colorable_appengine.go
generated
vendored
8
vendor/github.com/mattn/go-colorable/colorable_appengine.go
generated
vendored
@@ -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() {}
|
||||
}
|
||||
|
||||
8
vendor/github.com/mattn/go-colorable/colorable_others.go
generated
vendored
8
vendor/github.com/mattn/go-colorable/colorable_others.go
generated
vendored
@@ -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() {}
|
||||
}
|
||||
|
||||
28
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
28
vendor/github.com/mattn/go-colorable/colorable_windows.go
generated
vendored
@@ -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() {}
|
||||
}
|
||||
|
||||
7
vendor/github.com/mattn/go-colorable/go.mod
generated
vendored
7
vendor/github.com/mattn/go-colorable/go.mod
generated
vendored
@@ -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
|
||||
|
||||
9
vendor/github.com/mattn/go-colorable/go.sum
generated
vendored
9
vendor/github.com/mattn/go-colorable/go.sum
generated
vendored
@@ -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=
|
||||
|
||||
12
vendor/github.com/mattn/go-colorable/go.test.sh
generated
vendored
Normal file
12
vendor/github.com/mattn/go-colorable/go.test.sh
generated
vendored
Normal file
@@ -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
|
||||
15
vendor/github.com/mattn/go-isatty/.travis.yml
generated
vendored
15
vendor/github.com/mattn/go-isatty/.travis.yml
generated
vendored
@@ -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)
|
||||
|
||||
2
vendor/github.com/mattn/go-isatty/README.md
generated
vendored
2
vendor/github.com/mattn/go-isatty/README.md
generated
vendored
@@ -1,7 +1,7 @@
|
||||
# go-isatty
|
||||
|
||||
[](http://godoc.org/github.com/mattn/go-isatty)
|
||||
[](https://travis-ci.org/mattn/go-isatty)
|
||||
[](https://codecov.io/gh/mattn/go-isatty)
|
||||
[](https://coveralls.io/github/mattn/go-isatty?branch=master)
|
||||
[](https://goreportcard.com/report/mattn/go-isatty)
|
||||
|
||||
|
||||
4
vendor/github.com/mattn/go-isatty/go.mod
generated
vendored
4
vendor/github.com/mattn/go-isatty/go.mod
generated
vendored
@@ -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
|
||||
|
||||
6
vendor/github.com/mattn/go-isatty/go.sum
generated
vendored
6
vendor/github.com/mattn/go-isatty/go.sum
generated
vendored
@@ -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=
|
||||
|
||||
12
vendor/github.com/mattn/go-isatty/go.test.sh
generated
vendored
Normal file
12
vendor/github.com/mattn/go-isatty/go.test.sh
generated
vendored
Normal file
@@ -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
|
||||
23
vendor/github.com/mattn/go-isatty/isatty_android.go
generated
vendored
23
vendor/github.com/mattn/go-isatty/isatty_android.go
generated
vendored
@@ -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
|
||||
}
|
||||
12
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
12
vendor/github.com/mattn/go-isatty/isatty_bsd.go
generated
vendored
@@ -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
|
||||
|
||||
2
vendor/github.com/mattn/go-isatty/isatty_plan9.go
generated
vendored
2
vendor/github.com/mattn/go-isatty/isatty_plan9.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
1
vendor/github.com/mattn/go-isatty/isatty_tcgets.go
generated
vendored
1
vendor/github.com/mattn/go-isatty/isatty_tcgets.go
generated
vendored
@@ -1,6 +1,5 @@
|
||||
// +build linux aix
|
||||
// +build !appengine
|
||||
// +build !android
|
||||
|
||||
package isatty
|
||||
|
||||
|
||||
8
vendor/github.com/mattn/go-isatty/renovate.json
generated
vendored
Normal file
8
vendor/github.com/mattn/go-isatty/renovate.json
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"gomodTidy"
|
||||
]
|
||||
}
|
||||
18
vendor/gopkg.in/yaml.v2/.travis.yml
generated
vendored
18
vendor/gopkg.in/yaml.v2/.travis.yml
generated
vendored
@@ -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
|
||||
|
||||
109
vendor/gopkg.in/yaml.v2/scannerc.go
generated
vendored
109
vendor/gopkg.in/yaml.v2/scannerc.go
generated
vendored
@@ -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
|
||||
|
||||
2
vendor/gopkg.in/yaml.v2/yaml.go
generated
vendored
2
vendor/gopkg.in/yaml.v2/yaml.go
generated
vendored
@@ -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
|
||||
|
||||
1
vendor/gopkg.in/yaml.v2/yamlh.go
generated
vendored
1
vendor/gopkg.in/yaml.v2/yamlh.go
generated
vendored
@@ -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
|
||||
|
||||
|
||||
14
vendor/modules.txt
vendored
14
vendor/modules.txt
vendored
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user