diff --git a/CHANGELOG.md b/CHANGELOG.md index 92a6b6e3d3a3..aee4874b2ba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ IMPROVEMENTS: * core: Improved job deregistration error logging. [[GH-8745](https://github.com/hashicorp/nomad/issues/8745)] * api: Added support for cancellation contexts to HTTP API. [[GH-8836](https://github.com/hashicorp/nomad/issues/8836)] * driver/docker: upgrade pause container and detect architecture [[GH-8957](https://github.com/hashicorp/nomad/pull/8957)] + * client: consul-template updated to v0.25.0 [[GH-8988](https://github.com/hashicorp/nomad/pull/8988)] BUG FIXES: diff --git a/client/allocrunner/taskrunner/template/template.go b/client/allocrunner/taskrunner/template/template.go index caf3f99bcbf4..c37ed9d49331 100644 --- a/client/allocrunner/taskrunner/template/template.go +++ b/client/allocrunner/taskrunner/template/template.go @@ -576,7 +576,7 @@ func parseTemplateConfigs(config *TaskTemplateManagerConfig) (map[*ctconf.Templa ct.Contents = &tmpl.EmbeddedTmpl ct.LeftDelim = &tmpl.LeftDelim ct.RightDelim = &tmpl.RightDelim - ct.FunctionBlacklist = config.ClientConfig.TemplateConfig.FunctionBlacklist + ct.FunctionDenylist = config.ClientConfig.TemplateConfig.FunctionDenylist if !config.ClientConfig.TemplateConfig.DisableSandbox { ct.SandboxPath = &config.TaskDir } diff --git a/client/allocrunner/taskrunner/template/template_test.go b/client/allocrunner/taskrunner/template/template_test.go index 7c9db1368563..af4962cbfb93 100644 --- a/client/allocrunner/taskrunner/template/template_test.go +++ b/client/allocrunner/taskrunner/template/template_test.go @@ -134,8 +134,8 @@ func newTestHarness(t *testing.T, templates []*structs.Template, consul, vault b config: &config.Config{ Region: region, TemplateConfig: &config.ClientTemplateConfig{ - FunctionBlacklist: []string{"plugin"}, - DisableSandbox: false, + FunctionDenylist: []string{"plugin"}, + DisableSandbox: false, }}, emitRate: DefaultMaxTemplateEventRate, } diff --git a/client/config/config.go b/client/config/config.go index ab282691f4ee..5c7af0e0556b 100644 --- a/client/config/config.go +++ b/client/config/config.go @@ -271,8 +271,8 @@ type Config struct { } type ClientTemplateConfig struct { - FunctionBlacklist []string - DisableSandbox bool + FunctionDenylist []string + DisableSandbox bool } func (c *ClientTemplateConfig) Copy() *ClientTemplateConfig { @@ -282,7 +282,7 @@ func (c *ClientTemplateConfig) Copy() *ClientTemplateConfig { nc := new(ClientTemplateConfig) *nc = *c - nc.FunctionBlacklist = helper.CopySliceString(nc.FunctionBlacklist) + nc.FunctionDenylist = helper.CopySliceString(nc.FunctionDenylist) return nc } @@ -319,8 +319,8 @@ func DefaultConfig() *Config { DisableTaggedMetrics: false, DisableRemoteExec: false, TemplateConfig: &ClientTemplateConfig{ - FunctionBlacklist: []string{"plugin"}, - DisableSandbox: false, + FunctionDenylist: []string{"plugin"}, + DisableSandbox: false, }, BackwardsCompatibleMetrics: false, RPCHoldTimeout: 5 * time.Second, diff --git a/command/agent/agent.go b/command/agent/agent.go index 909b7c9f73ba..ed9a3e5560db 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -553,7 +553,7 @@ func convertClientConfig(agentConfig *Config) (*clientconfig.Config, error) { conf.ClientMaxPort = uint(agentConfig.Client.ClientMaxPort) conf.ClientMinPort = uint(agentConfig.Client.ClientMinPort) conf.DisableRemoteExec = agentConfig.Client.DisableRemoteExec - conf.TemplateConfig.FunctionBlacklist = agentConfig.Client.TemplateConfig.FunctionBlacklist + conf.TemplateConfig.FunctionDenylist = agentConfig.Client.TemplateConfig.FunctionDenylist conf.TemplateConfig.DisableSandbox = agentConfig.Client.TemplateConfig.DisableSandbox hvMap := make(map[string]*structs.ClientHostVolumeConfig, len(agentConfig.Client.HostVolumes)) diff --git a/command/agent/config.go b/command/agent/config.go index eb1539bcb645..05f8daf53a5e 100644 --- a/command/agent/config.go +++ b/command/agent/config.go @@ -307,9 +307,10 @@ type ClientConfig struct { // rendering type ClientTemplateConfig struct { - // FunctionBlacklist disables functions in consul-template that + // FunctionDenylist disables functions in consul-template that // are unsafe because they expose information from the client host. - FunctionBlacklist []string `hcl:"function_blacklist"` + // COMPAT(0.13) consul-template uses inclusive language from v0.25.0 - function_blacklist is kept for compatibility + FunctionDenylist []string `hcl:"function_denylist" hcl:"function_blacklist"` // DisableSandbox allows templates to access arbitrary files on the // client host. By default templates can access files only within @@ -827,8 +828,8 @@ func DevConfig(mode *devModeConfig) *Config { conf.Client.GCInodeUsageThreshold = 99 conf.Client.GCMaxAllocs = 50 conf.Client.TemplateConfig = &ClientTemplateConfig{ - FunctionBlacklist: []string{"plugin"}, - DisableSandbox: false, + FunctionDenylist: []string{"plugin"}, + DisableSandbox: false, } conf.Client.BindWildcardDefaultHostNetwork = true conf.Telemetry.PrometheusMetrics = true @@ -873,8 +874,8 @@ func DefaultConfig() *Config { RetryMaxAttempts: 0, }, TemplateConfig: &ClientTemplateConfig{ - FunctionBlacklist: []string{"plugin"}, - DisableSandbox: false, + FunctionDenylist: []string{"plugin"}, + DisableSandbox: false, }, BindWildcardDefaultHostNetwork: true, }, diff --git a/command/agent/config_test.go b/command/agent/config_test.go index 7c14432c7ef5..a54af7f94ea6 100644 --- a/command/agent/config_test.go +++ b/command/agent/config_test.go @@ -115,8 +115,8 @@ func TestConfig_Merge(t *testing.T) { ClientMaxPort: 19996, DisableRemoteExec: false, TemplateConfig: &ClientTemplateConfig{ - FunctionBlacklist: []string{"plugin"}, - DisableSandbox: false, + FunctionDenylist: []string{"plugin"}, + DisableSandbox: false, }, Reserved: &Resources{ CPU: 10, @@ -297,8 +297,8 @@ func TestConfig_Merge(t *testing.T) { MaxKillTimeout: "50s", DisableRemoteExec: false, TemplateConfig: &ClientTemplateConfig{ - FunctionBlacklist: []string{"plugin"}, - DisableSandbox: false, + FunctionDenylist: []string{"plugin"}, + DisableSandbox: false, }, Reserved: &Resources{ CPU: 15, diff --git a/go.mod b/go.mod index 8f119bad0e76..6c1901736200 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/gorilla/websocket v1.4.2 github.com/grpc-ecosystem/go-grpc-middleware v1.2.1-0.20200228141219-3ce3d519df39 github.com/hashicorp/consul v1.7.8 - github.com/hashicorp/consul-template v0.24.1 + github.com/hashicorp/consul-template v0.25.1 github.com/hashicorp/consul/api v1.6.0 github.com/hashicorp/consul/sdk v0.6.0 github.com/hashicorp/cronexpr v1.1.1 diff --git a/go.sum b/go.sum index 68358777517a..b39c66264f71 100644 --- a/go.sum +++ b/go.sum @@ -348,13 +348,11 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.2.1-0.20200228141219-3ce3d519df3 github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hashicorp/consul v1.7.8 h1:hp308KxAf3zWoGuwp2e+0UUhrm6qHjeBQk3jCZ+bjcY= github.com/hashicorp/consul v1.7.8/go.mod h1:urbfGaVZDmnXC6geg0LYPh/SRUk1E8nfmDHpz+Q0nLw= -github.com/hashicorp/consul-template v0.24.1 h1:96zTJ5YOq4HMTgtehXRvzGoQNEG2Z4jBYY5ofhq8/Cc= -github.com/hashicorp/consul-template v0.24.1/go.mod h1:KcTEopo2kCp7kww0d4oG7d3oX2Uou4hzb1Rs/wY9TVI= -github.com/hashicorp/consul/api v1.2.0/go.mod h1:1SIkFYi2ZTXUE5Kgt179+4hH33djo11+0Eo2XgTAtkw= +github.com/hashicorp/consul-template v0.25.1 h1:+D2s8eyRqWyX7GPNxeUi8tsyh8pRn3J6k8giEchPfKQ= +github.com/hashicorp/consul-template v0.25.1/go.mod h1:/vUsrJvDuuQHcxEw0zik+YXTS7ZKWZjQeaQhshBmfH0= github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU= github.com/hashicorp/consul/api v1.6.0 h1:SZB2hQW8AcTOpfDmiVblQbijxzsRuiyy0JpHfabvHio= github.com/hashicorp/consul/api v1.6.0/go.mod h1:1NSuaUUkFaJzMasbfq/11wKYWSR67Xn6r2DXKhuDNFg= -github.com/hashicorp/consul/sdk v0.2.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.4.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= github.com/hashicorp/consul/sdk v0.6.0 h1:FfhMEkwvQl57CildXJyGHnwGGM4HMODGyfjGwNM1Vdw= github.com/hashicorp/consul/sdk v0.6.0/go.mod h1:fY08Y9z5SvJqevyZNy6WWPXiG3KwBPAvlcdx16zZ0fM= @@ -410,7 +408,6 @@ github.com/hashicorp/go-raftchunking v0.6.1/go.mod h1:cGlg3JtDy7qy6c/3Bu660Mic1J github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4 h1:1BZvpawXoJCWX6pNtow9+rpEj+3itIlutiqnntI6jOE= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= @@ -910,7 +907,6 @@ golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/hashicorp/consul-template/child/child.go b/vendor/github.com/hashicorp/consul-template/child/child.go index 3c94816f596b..1b6742707387 100644 --- a/vendor/github.com/hashicorp/consul-template/child/child.go +++ b/vendor/github.com/hashicorp/consul-template/child/child.go @@ -290,14 +290,14 @@ func (c *Child) start() error { // down the exit channel. c.stopLock.RLock() defer c.stopLock.RUnlock() - if c.stopped { - return + if !c.stopped { + select { + case <-c.stopCh: + case exitCh <- code: + } } - select { - case <-c.stopCh: - case exitCh <- code: - } + close(exitCh) }() c.exitCh = exitCh @@ -365,16 +365,13 @@ func (c *Child) reload() error { return c.signal(c.reloadSignal) } +// kill sends the signal to kill the process using the configured signal +// if set, else the default system signal func (c *Child) kill(immediately bool) { - if !c.running() { - return - } - exited := false - process := c.cmd.Process - - if c.cmd.ProcessState != nil { + if !c.running() { log.Printf("[DEBUG] (child) Kill() called but process dead; not waiting for splay.") + return } else if immediately { log.Printf("[DEBUG] (child) Kill() called but performing immediate shutdown; not waiting for splay.") } else { @@ -384,6 +381,9 @@ func (c *Child) kill(immediately bool) { } } + exited := false + process := c.cmd.Process + if c.killSignal != nil { if err := process.Signal(c.killSignal); err == nil { // Wait a few seconds for it to exit @@ -410,6 +410,11 @@ func (c *Child) kill(immediately bool) { } func (c *Child) running() bool { + select { + case <-c.exitCh: + return false + default: + } return c.cmd != nil && c.cmd.Process != nil } diff --git a/vendor/github.com/hashicorp/consul-template/config/config.go b/vendor/github.com/hashicorp/consul-template/config/config.go index b027040937b9..a4d31d5a9904 100644 --- a/vendor/github.com/hashicorp/consul-template/config/config.go +++ b/vendor/github.com/hashicorp/consul-template/config/config.go @@ -33,6 +33,9 @@ const ( // DefaultKillSignal is the default signal for termination. DefaultKillSignal = syscall.SIGINT + + // DefaultBlockQueryWaitTime is amount of time in seconds to do a blocking query for + DefaultBlockQueryWaitTime = 60 * time.Second ) var ( @@ -48,6 +51,9 @@ type Config struct { // Dedup is used to configure the dedup settings Dedup *DedupConfig `mapstructure:"deduplicate"` + // DefaultDelims is used to configure the default delimiters for templates + DefaultDelims *DefaultDelims `mapstructure:"default_delimiters"` + // Exec is the configuration for exec/supervise mode. Exec *ExecConfig `mapstructure:"exec"` @@ -84,6 +90,9 @@ type Config struct { // Additional command line options // Run once, executing each template exactly once, and exit Once bool + + // BlockQueryWaitTime is amount of time in seconds to do a blocking query for + BlockQueryWaitTime *time.Duration `mapstructure:"block_query_wait"` } // Copy returns a deep copy of the current configuration. This is useful because @@ -104,6 +113,10 @@ func (c *Config) Copy() *Config { o.Dedup = c.Dedup.Copy() } + if c.DefaultDelims != nil { + o.DefaultDelims = c.DefaultDelims.Copy() + } + if c.Exec != nil { o.Exec = c.Exec.Copy() } @@ -136,6 +149,8 @@ func (c *Config) Copy() *Config { o.Once = c.Once + o.BlockQueryWaitTime = c.BlockQueryWaitTime + return &o } @@ -163,6 +178,10 @@ func (c *Config) Merge(o *Config) *Config { r.Dedup = r.Dedup.Merge(o.Dedup) } + if o.DefaultDelims != nil { + r.DefaultDelims = r.DefaultDelims.Merge(o.DefaultDelims) + } + if o.Exec != nil { r.Exec = r.Exec.Merge(o.Exec) } @@ -205,6 +224,8 @@ func (c *Config) Merge(o *Config) *Config { r.Once = o.Once + r.BlockQueryWaitTime = o.BlockQueryWaitTime + return r } @@ -229,6 +250,7 @@ func Parse(s string) (*Config, error) { "consul.ssl", "consul.transport", "deduplicate", + "default_delimiters", "env", "exec", "exec.env", @@ -383,6 +405,7 @@ func (c *Config) GoString() string { return fmt.Sprintf("&Config{"+ "Consul:%#v, "+ "Dedup:%#v, "+ + "DefaultDelims:%#v, "+ "Exec:%#v, "+ "KillSignal:%s, "+ "LogLevel:%s, "+ @@ -394,9 +417,11 @@ func (c *Config) GoString() string { "Vault:%#v, "+ "Wait:%#v,"+ "Once:%#v"+ + "BlockQueryWaitTime:%#v"+ "}", c.Consul, c.Dedup, + c.DefaultDelims, c.Exec, SignalGoString(c.KillSignal), StringGoString(c.LogLevel), @@ -408,6 +433,7 @@ func (c *Config) GoString() string { c.Vault, c.Wait, c.Once, + TimeDurationGoString(c.BlockQueryWaitTime), ) } @@ -436,13 +462,14 @@ func (expected *Config) Diff(actual *Config) string { // variables may be set which control the values for the default configuration. func DefaultConfig() *Config { return &Config{ - Consul: DefaultConsulConfig(), - Dedup: DefaultDedupConfig(), - Exec: DefaultExecConfig(), - Syslog: DefaultSyslogConfig(), - Templates: DefaultTemplateConfigs(), - Vault: DefaultVaultConfig(), - Wait: DefaultWaitConfig(), + Consul: DefaultConsulConfig(), + Dedup: DefaultDedupConfig(), + DefaultDelims: DefaultDefaultDelims(), + Exec: DefaultExecConfig(), + Syslog: DefaultSyslogConfig(), + Templates: DefaultTemplateConfigs(), + Vault: DefaultVaultConfig(), + Wait: DefaultWaitConfig(), } } @@ -465,6 +492,10 @@ func (c *Config) Finalize() { } c.Dedup.Finalize() + if c.DefaultDelims == nil { + c.DefaultDelims = DefaultDefaultDelims() + } + if c.Exec == nil { c.Exec = DefaultExecConfig() } @@ -517,6 +548,11 @@ func (c *Config) Finalize() { if c.Once { c.Wait = &WaitConfig{Enabled: Bool(false)} } + + // defaults WaitTime to 60 seconds + if c.BlockQueryWaitTime == nil { + c.BlockQueryWaitTime = TimeDuration(DefaultBlockQueryWaitTime) + } } func stringFromEnv(list []string, def string) *string { diff --git a/vendor/github.com/hashicorp/consul-template/config/consul.go b/vendor/github.com/hashicorp/consul-template/config/consul.go index ca79ba8b66aa..9f153c1e7edc 100644 --- a/vendor/github.com/hashicorp/consul-template/config/consul.go +++ b/vendor/github.com/hashicorp/consul-template/config/consul.go @@ -8,6 +8,10 @@ type ConsulConfig struct { // Address is the address of the Consul server. It may be an IP or FQDN. Address *string + // Namespace is the Consul namespace to use for reading/writing. This can + // also be set via the CONSUL_NAMESPACE environment variable. + Namespace *string `mapstructure:"namespace"` + // Auth is the HTTP basic authentication for communicating with Consul. Auth *AuthConfig `mapstructure:"auth"` @@ -46,6 +50,8 @@ func (c *ConsulConfig) Copy() *ConsulConfig { o.Address = c.Address + o.Namespace = c.Namespace + if c.Auth != nil { o.Auth = c.Auth.Copy() } @@ -89,6 +95,10 @@ func (c *ConsulConfig) Merge(o *ConsulConfig) *ConsulConfig { r.Address = o.Address } + if o.Namespace != nil { + r.Namespace = o.Namespace + } + if o.Auth != nil { r.Auth = r.Auth.Merge(o.Auth) } @@ -120,6 +130,10 @@ func (c *ConsulConfig) Finalize() { }, "") } + if c.Namespace == nil { + c.Namespace = stringFromEnv([]string{"CONSUL_NAMESPACE"}, "") + } + if c.Auth == nil { c.Auth = DefaultAuthConfig() } @@ -156,6 +170,7 @@ func (c *ConsulConfig) GoString() string { return fmt.Sprintf("&ConsulConfig{"+ "Address:%s, "+ + "Namespace:%s, "+ "Auth:%#v, "+ "Retry:%#v, "+ "SSL:%#v, "+ @@ -163,6 +178,7 @@ func (c *ConsulConfig) GoString() string { "Transport:%#v"+ "}", StringGoString(c.Address), + StringGoString(c.Namespace), c.Auth, c.Retry, c.SSL, diff --git a/vendor/github.com/hashicorp/consul-template/config/dedup.go b/vendor/github.com/hashicorp/consul-template/config/dedup.go index 247855a938e3..57c6f24a84b6 100644 --- a/vendor/github.com/hashicorp/consul-template/config/dedup.go +++ b/vendor/github.com/hashicorp/consul-template/config/dedup.go @@ -15,6 +15,9 @@ const ( // DefaultDedupMaxStale is the default max staleness for the deduplication // manager. DefaultDedupMaxStale = DefaultMaxStale + + // DefaultDedupBlockQueryWaitTime is the default amount of time to do a blocking query for the deduplication + DefaultDedupBlockQueryWaitTime = 60 * time.Second ) // DedupConfig is used to enable the de-duplication mode, which depends @@ -32,6 +35,9 @@ type DedupConfig struct { // TTL is the Session TTL used for lock acquisition, defaults to 15 seconds. TTL *time.Duration `mapstructure:"ttl"` + + // BlockQueryWaitTime is amount of time to do a blocking query for, defaults to 60 seconds. + BlockQueryWaitTime *time.Duration `mapstructure:"block_query_wait"` } // DefaultDedupConfig returns a configuration that is populated with the @@ -51,6 +57,7 @@ func (c *DedupConfig) Copy() *DedupConfig { o.MaxStale = c.MaxStale o.Prefix = c.Prefix o.TTL = c.TTL + o.BlockQueryWaitTime = c.BlockQueryWaitTime return &o } @@ -88,6 +95,10 @@ func (c *DedupConfig) Merge(o *DedupConfig) *DedupConfig { r.TTL = o.TTL } + if o.BlockQueryWaitTime != nil { + r.BlockQueryWaitTime = o.BlockQueryWaitTime + } + return r } @@ -97,7 +108,8 @@ func (c *DedupConfig) Finalize() { c.Enabled = Bool(false || TimeDurationPresent(c.MaxStale) || StringPresent(c.Prefix) || - TimeDurationPresent(c.TTL)) + TimeDurationPresent(c.TTL) || + TimeDurationPresent(c.BlockQueryWaitTime)) } if c.MaxStale == nil { @@ -111,6 +123,10 @@ func (c *DedupConfig) Finalize() { if c.TTL == nil { c.TTL = TimeDuration(DefaultDedupTTL) } + + if c.BlockQueryWaitTime == nil { + c.BlockQueryWaitTime = TimeDuration(DefaultDedupBlockQueryWaitTime) + } } // GoString defines the printable version of this struct. @@ -122,11 +138,13 @@ func (c *DedupConfig) GoString() string { "Enabled:%s, "+ "MaxStale:%s, "+ "Prefix:%s, "+ - "TTL:%s"+ + "TTL:%s, "+ + "BlockQueryWaitTime:%s"+ "}", BoolGoString(c.Enabled), TimeDurationGoString(c.MaxStale), StringGoString(c.Prefix), TimeDurationGoString(c.TTL), + TimeDurationGoString(c.BlockQueryWaitTime), ) } diff --git a/vendor/github.com/hashicorp/consul-template/config/env.go b/vendor/github.com/hashicorp/consul-template/config/env.go index a9a4b1ebe848..0d93aef6aca8 100644 --- a/vendor/github.com/hashicorp/consul-template/config/env.go +++ b/vendor/github.com/hashicorp/consul-template/config/env.go @@ -11,15 +11,21 @@ import ( // variable filtering. You should not use this directly and it is only public // for mapstructure's decoding. type EnvConfig struct { - // BlacklistEnv specifies a list of environment variables to explicitly + // Denylist specifies a list of environment variables to explicitly // exclude from the list of environment variables populated to the child. - // If both WhitelistEnv and BlacklistEnv are provided, BlacklistEnv takes - // precedence over the values in WhitelistEnv. - Blacklist []string `mapstructure:"blacklist"` + // If both Allowlist and Denylist are provided, Denylist takes + // precedence over the values in Allowlist. + Denylist []string `mapstructure:"denylist"` + + // DenylistDeprecated is the backward compatible option for Denylist for + // configuration supported by v0.25.0 and older. This should not be used + // directly, use Denylist instead. Values from this are combined to + // Denylist in Finalize(). + DenylistDeprecated []string `mapstructure:"blacklist" json:"-"` // CustomEnv specifies custom environment variables to pass to the child // process. These are provided programmatically, override any environment - // variables of the same name, are ignored from whitelist/blacklist, and + // variables of the same name, are ignored from allowlist/denylist, and // are still included even if PristineEnv is set to true. Custom []string `mapstructure:"custom"` @@ -27,9 +33,15 @@ type EnvConfig struct { // environment. Pristine *bool `mapstructure:"pristine"` - // WhitelistEnv specifies a list of environment variables to exclusively + // Allowlist specifies a list of environment variables to exclusively // include in the list of environment variables populated to the child. - Whitelist []string `mapstructure:"whitelist"` + Allowlist []string `mapstructure:"allowlist"` + + // AllowlistDeprecated is the backward compatible option for Allowlist for + // configuration supported by v0.25.0 and older. This should not be used + // directly, use Allowlist instead. Values from this are combined to + // Allowlist in Finalize(). + AllowlistDeprecated []string `mapstructure:"whitelist" json:"-"` } // DefaultEnvConfig returns a configuration that is populated with the @@ -46,8 +58,12 @@ func (c *EnvConfig) Copy() *EnvConfig { var o EnvConfig - if c.Blacklist != nil { - o.Blacklist = append([]string{}, c.Blacklist...) + if c.Denylist != nil { + o.Denylist = append([]string{}, c.Denylist...) + } + + if c.DenylistDeprecated != nil { + o.DenylistDeprecated = append([]string{}, c.DenylistDeprecated...) } if c.Custom != nil { @@ -56,8 +72,12 @@ func (c *EnvConfig) Copy() *EnvConfig { o.Pristine = c.Pristine - if c.Whitelist != nil { - o.Whitelist = append([]string{}, c.Whitelist...) + if c.Allowlist != nil { + o.Allowlist = append([]string{}, c.Allowlist...) + } + + if c.AllowlistDeprecated != nil { + o.AllowlistDeprecated = append([]string{}, c.AllowlistDeprecated...) } return &o @@ -81,8 +101,12 @@ func (c *EnvConfig) Merge(o *EnvConfig) *EnvConfig { r := c.Copy() - if o.Blacklist != nil { - r.Blacklist = append(r.Blacklist, o.Blacklist...) + if o.Denylist != nil { + r.Denylist = append(r.Denylist, o.Denylist...) + } + + if o.DenylistDeprecated != nil { + r.DenylistDeprecated = append(r.DenylistDeprecated, o.DenylistDeprecated...) } if o.Custom != nil { @@ -93,16 +117,20 @@ func (c *EnvConfig) Merge(o *EnvConfig) *EnvConfig { r.Pristine = o.Pristine } - if o.Whitelist != nil { - r.Whitelist = append(r.Whitelist, o.Whitelist...) + if o.Allowlist != nil { + r.Allowlist = append(r.Allowlist, o.Allowlist...) + } + + if o.AllowlistDeprecated != nil { + r.AllowlistDeprecated = append(r.AllowlistDeprecated, o.AllowlistDeprecated...) } return r } // Env calculates and returns the finalized environment for this exec -// configuration. It takes into account pristine, custom environment, whitelist, -// and blacklist values. +// configuration. It takes into account pristine, custom environment, allowlist, +// and denylist values. func (c *EnvConfig) Env() []string { // In pristine mode, just return the custom environment. If the user did not // specify a custom environment, just return the empty slice to force an @@ -136,22 +164,30 @@ func (c *EnvConfig) Env() []string { return false } - // Pull out any envvars that match the whitelist. - if len(c.Whitelist) > 0 { + // Pull out any envvars that match the allowlist. + // Combining lists on each reference may be slightly inefficient but this + // allows for out of order method calls, not requiring the config to be + // finalized first. + allowlist := combineLists(c.Allowlist, c.AllowlistDeprecated) + if len(allowlist) > 0 { newKeys := make([]string, 0, len(keys)) for _, k := range keys { - if anyGlobMatch(k, c.Whitelist) { + if anyGlobMatch(k, allowlist) { newKeys = append(newKeys, k) } } keys = newKeys } - // Remove any envvars that match the blacklist. - if len(c.Blacklist) > 0 { + // Remove any envvars that match the denylist. + // Combining lists on each reference may be slightly inefficient but this + // allows for out of order method calls, not requiring the config to be + // finalized first. + denylist := combineLists(c.Denylist, c.DenylistDeprecated) + if len(denylist) > 0 { newKeys := make([]string, 0, len(keys)) for _, k := range keys { - if !anyGlobMatch(k, c.Blacklist) { + if !anyGlobMatch(k, denylist) { newKeys = append(newKeys, k) } } @@ -172,8 +208,11 @@ func (c *EnvConfig) Env() []string { // Finalize ensures there no nil pointers. func (c *EnvConfig) Finalize() { - if c.Blacklist == nil { - c.Blacklist = []string{} + if c.Denylist == nil && c.DenylistDeprecated == nil { + c.Denylist = []string{} + c.DenylistDeprecated = []string{} + } else { + c.Denylist = combineLists(c.Denylist, c.DenylistDeprecated) } if c.Custom == nil { @@ -184,8 +223,11 @@ func (c *EnvConfig) Finalize() { c.Pristine = Bool(false) } - if c.Whitelist == nil { - c.Whitelist = []string{} + if c.Allowlist == nil && c.AllowlistDeprecated == nil { + c.Allowlist = []string{} + c.AllowlistDeprecated = []string{} + } else { + c.Allowlist = combineLists(c.Allowlist, c.AllowlistDeprecated) } } @@ -196,14 +238,33 @@ func (c *EnvConfig) GoString() string { } return fmt.Sprintf("&EnvConfig{"+ - "Blacklist:%v, "+ + "Denylist:%v, "+ "Custom:%v, "+ "Pristine:%s, "+ - "Whitelist:%v"+ + "Allowlist:%v"+ "}", - c.Blacklist, + combineLists(c.Denylist, c.DenylistDeprecated), c.Custom, BoolGoString(c.Pristine), - c.Whitelist, + combineLists(c.Allowlist, c.AllowlistDeprecated), ) } + +// combineLists makes a new list that combines 2 lists by adding values from +// the second list without removing any duplicates from the first. +func combineLists(a, b []string) []string { + combined := make([]string, len(a), len(a)+len(b)) + m := make(map[string]bool) + for i, v := range a { + m[v] = true + combined[i] = v + } + + for _, v := range b { + if !m[v] { + combined = append(combined, v) + } + } + + return combined +} diff --git a/vendor/github.com/hashicorp/consul-template/config/syslog.go b/vendor/github.com/hashicorp/consul-template/config/syslog.go index 0de67199d7d2..14b9127c29fa 100644 --- a/vendor/github.com/hashicorp/consul-template/config/syslog.go +++ b/vendor/github.com/hashicorp/consul-template/config/syslog.go @@ -1,16 +1,26 @@ package config -import "fmt" +import ( + "fmt" + + "github.com/hashicorp/consul-template/version" +) const ( // DefaultSyslogFacility is the default facility to log to. DefaultSyslogFacility = "LOCAL0" ) +var ( + // DefaultSyslogName is the default app name in syslog. + DefaultSyslogName = version.Name +) + // SyslogConfig is the configuration for syslog. type SyslogConfig struct { Enabled *bool `mapstructure:"enabled"` Facility *string `mapstructure:"facility"` + Name *string `mapstructure:"name"` } // DefaultSyslogConfig returns a configuration that is populated with the @@ -28,6 +38,7 @@ func (c *SyslogConfig) Copy() *SyslogConfig { var o SyslogConfig o.Enabled = c.Enabled o.Facility = c.Facility + o.Name = c.Name return &o } @@ -57,18 +68,26 @@ func (c *SyslogConfig) Merge(o *SyslogConfig) *SyslogConfig { r.Facility = o.Facility } + if o.Name != nil { + r.Name = o.Name + } + return r } // Finalize ensures there no nil pointers. func (c *SyslogConfig) Finalize() { if c.Enabled == nil { - c.Enabled = Bool(StringPresent(c.Facility)) + c.Enabled = Bool(StringPresent(c.Facility) || StringPresent(c.Name)) } if c.Facility == nil { c.Facility = String(DefaultSyslogFacility) } + + if c.Name == nil { + c.Name = String(DefaultSyslogName) + } } // GoString defines the printable version of this struct. @@ -80,8 +99,10 @@ func (c *SyslogConfig) GoString() string { return fmt.Sprintf("&SyslogConfig{"+ "Enabled:%s, "+ "Facility:%s"+ + "Name:%s"+ "}", BoolGoString(c.Enabled), StringGoString(c.Facility), + StringGoString(c.Name), ) } diff --git a/vendor/github.com/hashicorp/consul-template/config/template.go b/vendor/github.com/hashicorp/consul-template/config/template.go index 4f69bfb6033f..a42e4d87fcac 100644 --- a/vendor/github.com/hashicorp/consul-template/config/template.go +++ b/vendor/github.com/hashicorp/consul-template/config/template.go @@ -76,9 +76,15 @@ type TemplateConfig struct { LeftDelim *string `mapstructure:"left_delimiter"` RightDelim *string `mapstructure:"right_delimiter"` - // FunctionBlacklist is a list of functions that this template is not + // FunctionDenylist is a list of functions that this template is not // permitted to run. - FunctionBlacklist []string `mapstructure:"function_blacklist"` + FunctionDenylist []string `mapstructure:"function_denylist"` + + // FunctionDenylistDeprecated is the backward compatible option for + // FunctionDenylist for configuration supported by v0.25.0 and older. This + // should not be used directly, use FunctionDenylist instead. Values from + // this are combined to FunctionDenylist in Finalize(). + FunctionDenylistDeprecated []string `mapstructure:"function_blacklist" json:"-"` // SandboxPath adds a prefix to any path provided to the `file` function // and causes an error if a relative path tries to traverse outside that @@ -132,9 +138,14 @@ func (c *TemplateConfig) Copy() *TemplateConfig { o.LeftDelim = c.LeftDelim o.RightDelim = c.RightDelim - for _, fun := range c.FunctionBlacklist { - o.FunctionBlacklist = append(o.FunctionBlacklist, fun) + for _, fun := range c.FunctionDenylist { + o.FunctionDenylist = append(o.FunctionDenylist, fun) + } + + for _, fun := range c.FunctionDenylistDeprecated { + o.FunctionDenylistDeprecated = append(o.FunctionDenylistDeprecated, fun) } + o.SandboxPath = c.SandboxPath return &o @@ -210,9 +221,14 @@ func (c *TemplateConfig) Merge(o *TemplateConfig) *TemplateConfig { r.RightDelim = o.RightDelim } - for _, fun := range o.FunctionBlacklist { - r.FunctionBlacklist = append(r.FunctionBlacklist, fun) + for _, fun := range o.FunctionDenylist { + r.FunctionDenylist = append(r.FunctionDenylist, fun) } + + for _, fun := range o.FunctionDenylistDeprecated { + r.FunctionDenylistDeprecated = append(r.FunctionDenylistDeprecated, fun) + } + if o.SandboxPath != nil { r.SandboxPath = o.SandboxPath } @@ -288,6 +304,13 @@ func (c *TemplateConfig) Finalize() { if c.SandboxPath == nil { c.SandboxPath = String("") } + + if c.FunctionDenylist == nil && c.FunctionDenylistDeprecated == nil { + c.FunctionDenylist = []string{} + c.FunctionDenylistDeprecated = []string{} + } else { + c.FunctionDenylist = combineLists(c.FunctionDenylist, c.FunctionDenylistDeprecated) + } } // GoString defines the printable version of this struct. @@ -309,8 +332,8 @@ func (c *TemplateConfig) GoString() string { "Source:%s, "+ "Wait:%#v, "+ "LeftDelim:%s, "+ - "RightDelim:%s"+ - "FunctionBlacklist:%s"+ + "RightDelim:%s, "+ + "FunctionDenylist:%s, "+ "SandboxPath:%s"+ "}", BoolGoString(c.Backup), @@ -326,7 +349,7 @@ func (c *TemplateConfig) GoString() string { c.Wait, StringGoString(c.LeftDelim), StringGoString(c.RightDelim), - c.FunctionBlacklist, + combineLists(c.FunctionDenylist, c.FunctionDenylistDeprecated), StringGoString(c.SandboxPath), ) } diff --git a/vendor/github.com/hashicorp/consul-template/config/vault.go b/vendor/github.com/hashicorp/consul-template/config/vault.go index 49c2acaf6507..5eb727c3aeae 100644 --- a/vendor/github.com/hashicorp/consul-template/config/vault.go +++ b/vendor/github.com/hashicorp/consul-template/config/vault.go @@ -193,16 +193,6 @@ func (c *VaultConfig) Finalize() { 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() } @@ -258,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() } diff --git a/vendor/github.com/hashicorp/consul-template/dependency/client_set.go b/vendor/github.com/hashicorp/consul-template/dependency/client_set.go index e2bceb773820..b891f3a39ff8 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/client_set.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/client_set.go @@ -38,6 +38,7 @@ type vaultClient struct { // CreateConsulClientInput is used as input to the CreateConsulClient function. type CreateConsulClientInput struct { Address string + Namespace string Token string AuthEnabled bool AuthUsername string @@ -95,6 +96,10 @@ func (c *ClientSet) CreateConsulClient(i *CreateConsulClientInput) error { consulConfig.Address = i.Address } + if i.Namespace != "" { + consulConfig.Namespace = i.Namespace + } + if i.Token != "" { consulConfig.Token = i.Token } diff --git a/vendor/github.com/hashicorp/consul-template/dependency/health_service.go b/vendor/github.com/hashicorp/consul-template/dependency/health_service.go index 20fae8b765ca..941992531934 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/health_service.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/health_service.go @@ -51,6 +51,7 @@ type HealthService struct { Checks api.HealthChecks Status string Port int + Weights api.AgentWeights } // HealthServiceQuery is the representation of all a service query in Consul. @@ -187,9 +188,10 @@ func (d *HealthServiceQuery) Fetch(clients *ClientSet, opts *QueryOptions) (inte Name: entry.Service.Service, Tags: ServiceTags( deepCopyAndSortTags(entry.Service.Tags)), - Status: status, - Checks: entry.Checks, - Port: entry.Service.Port, + Status: status, + Checks: entry.Checks, + Port: entry.Service.Port, + Weights: entry.Service.Weights, }) } diff --git a/vendor/github.com/hashicorp/consul-template/dependency/vault_common.go b/vendor/github.com/hashicorp/consul-template/dependency/vault_common.go index 6abe69cfd142..e579f8958b79 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/vault_common.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/vault_common.go @@ -3,13 +3,9 @@ package dependency import ( "log" "math/rand" - "path" - "strings" "time" - "crypto/x509" - "encoding/pem" - + "encoding/json" "github.com/hashicorp/vault/api" ) @@ -105,22 +101,6 @@ func renewSecret(clients *ClientSet, d renewer) error { } } -// durationFrom cert gets the duration of validity from cert data and -// returns that value as an integer number of seconds -func durationFromCert(certData string) int { - block, _ := pem.Decode([]byte(certData)) - if block == nil { - return -1 - } - cert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - log.Printf("[WARN] Unable to parse certificate data: %s", err) - return -1 - } - - return int(cert.NotAfter.Sub(cert.NotBefore).Seconds()) -} - // leaseCheckWait accepts a secret and returns the recommended amount of // time to sleep. func leaseCheckWait(s *Secret) time.Duration { @@ -131,12 +111,25 @@ func leaseCheckWait(s *Secret) time.Duration { } // Handle if this is a certificate with no lease - if certInterface, ok := s.Data["certificate"]; ok && s.LeaseID == "" { - if certData, ok := certInterface.(string); ok { - newDuration := durationFromCert(certData) - if newDuration > 0 { - log.Printf("[DEBUG] Found certificate and set lease duration to %d seconds", newDuration) - base = newDuration + if _, ok := s.Data["certificate"]; ok && s.LeaseID == "" { + if expInterface, ok := s.Data["expiration"]; ok { + if expData, err := expInterface.(json.Number).Int64(); err == nil { + base = int(expData - time.Now().Unix()) + log.Printf("[DEBUG] Found certificate and set lease duration to %d seconds", base) + } + } + } + + // 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 } } } @@ -156,7 +149,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. @@ -332,17 +327,3 @@ func isKVv2(client *api.Client, path string) (string, bool, error) { return mountPath, false, nil } - -func addPrefixToVKVPath(p, mountPath, apiPrefix string) string { - switch { - case p == mountPath, p == strings.TrimSuffix(mountPath, "/"): - 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) { - return path.Join(mountPath, p) - } - return path.Join(mountPath, apiPrefix, p) - } -} diff --git a/vendor/github.com/hashicorp/consul-template/dependency/vault_read.go b/vendor/github.com/hashicorp/consul-template/dependency/vault_read.go index 00ebf27ec0db..ab71e9eb03eb 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/vault_read.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/vault_read.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "net/url" + "path" "strings" "time" @@ -122,6 +123,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) } @@ -142,7 +146,7 @@ func (d *VaultReadQuery) readSecret(clients *ClientSet, opts *QueryOptions) (*ap isKVv2 = false d.secretPath = d.rawPath } else if isKVv2 { - d.secretPath = addPrefixToVKVPath(d.rawPath, mountPath, "data") + d.secretPath = shimKVv2Path(d.rawPath, mountPath) } else { d.secretPath = d.rawPath } @@ -173,3 +177,21 @@ func deletedKVv2(s *api.Secret) bool { } return false } + +// shimKVv2Path aligns the supported legacy path to KV v2 specs by inserting +// /data/ into the path for reading secrets. Paths for metadata are not modified. +func shimKVv2Path(rawPath, mountPath string) string { + switch { + case rawPath == mountPath, rawPath == strings.TrimSuffix(mountPath, "/"): + return path.Join(mountPath, "data") + default: + p := strings.TrimPrefix(rawPath, mountPath) + + // Only add /data/ prefix to the path if neither /data/ or /metadata/ are + // present. + if strings.HasPrefix(p, "data/") || strings.HasPrefix(p, "metadata/") { + return rawPath + } + return path.Join(mountPath, "data", p) + } +} diff --git a/vendor/github.com/hashicorp/consul-template/dependency/vault_token.go b/vendor/github.com/hashicorp/consul-template/dependency/vault_token.go index 93ad5984ac6d..6e962906ce98 100644 --- a/vendor/github.com/hashicorp/consul-template/dependency/vault_token.go +++ b/vendor/github.com/hashicorp/consul-template/dependency/vault_token.go @@ -47,7 +47,6 @@ func (d *VaultTokenQuery) Fetch(clients *ClientSet, opts *QueryOptions, if err != nil { return nil, nil, errors.Wrap(err, d.String()) } - renewSecret(clients, d) } return nil, nil, ErrLeaseExpired diff --git a/vendor/github.com/hashicorp/consul-template/manager/runner.go b/vendor/github.com/hashicorp/consul-template/manager/runner.go index 7be178a45e22..f14a4c95dcba 100644 --- a/vendor/github.com/hashicorp/consul-template/manager/runner.go +++ b/vendor/github.com/hashicorp/consul-template/manager/runner.go @@ -102,6 +102,7 @@ type Runner struct { // template and command runtime with. These environment variables will be // available in both the command's environment as well as the template's // environment. + // NOTE this is only used when CT is being used as a library. Env map[string]string // stopLock is the lock around checking if the runner can be stopped @@ -556,23 +557,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 +585,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 { @@ -873,14 +874,23 @@ 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), - FunctionBlacklist: ctmpl.FunctionBlacklist, - SandboxPath: config.StringVal(ctmpl.SandboxPath), + Source: config.StringVal(ctmpl.Source), + Contents: config.StringVal(ctmpl.Contents), + ErrMissingKey: config.BoolVal(ctmpl.ErrMissingKey), + LeftDelim: leftDelim, + RightDelim: rightDelim, + FunctionDenylist: ctmpl.FunctionDenylist, + SandboxPath: config.StringVal(ctmpl.SandboxPath), }) if err != nil { return err @@ -1240,6 +1250,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), @@ -1296,6 +1307,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()), diff --git a/vendor/github.com/hashicorp/consul-template/renderer/renderer.go b/vendor/github.com/hashicorp/consul-template/renderer/renderer.go index 59931c19e628..366eab81ded0 100644 --- a/vendor/github.com/hashicorp/consul-template/renderer/renderer.go +++ b/vendor/github.com/hashicorp/consul-template/renderer/renderer.go @@ -60,11 +60,12 @@ type RenderResult struct { // whether it would have rendered and actually did render. func Render(i *RenderInput) (*RenderResult, error) { existing, err := ioutil.ReadFile(i.Path) - if err != nil && !os.IsNotExist(err) { + fileExists := !os.IsNotExist(err) + if err != nil && fileExists { return nil, errors.Wrap(err, "failed reading file") } - if bytes.Equal(existing, i.Contents) { + if bytes.Equal(existing, i.Contents) && fileExists { return &RenderResult{ DidRender: false, WouldRender: true, diff --git a/vendor/github.com/hashicorp/consul-template/template/funcs.go b/vendor/github.com/hashicorp/consul-template/template/funcs.go index 12e35b888e45..ecbdb72a3bcd 100644 --- a/vendor/github.com/hashicorp/consul-template/template/funcs.go +++ b/vendor/github.com/hashicorp/consul-template/template/funcs.go @@ -2,7 +2,9 @@ package template import ( "bytes" + "crypto/sha256" "encoding/base64" + "encoding/hex" "encoding/json" "fmt" "io/ioutil" @@ -388,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" @@ -981,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. @@ -1346,8 +1359,150 @@ func modulo(b, a interface{}) (interface{}, error) { } } -// blacklisted always returns an error, to be used in place of blacklisted template functions -func blacklisted(...string) (string, 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) + } +} + +// denied always returns an error, to be used in place of denied template functions +func denied(...string) (string, error) { return "", errors.New("function is disabled") } @@ -1379,3 +1534,11 @@ func sockaddr(args ...string) (string, error) { } return k, nil } + +// sha256Hex return the sha256 hex of a string +func sha256Hex(item string) (string, error) { + h := sha256.New() + h.Write([]byte(item)) + output := hex.EncodeToString(h.Sum(nil)) + return output, nil +} diff --git a/vendor/github.com/hashicorp/consul-template/template/template.go b/vendor/github.com/hashicorp/consul-template/template/template.go index b56a79e2e9b7..7b70bca559bb 100644 --- a/vendor/github.com/hashicorp/consul-template/template/template.go +++ b/vendor/github.com/hashicorp/consul-template/template/template.go @@ -15,12 +15,12 @@ import ( var ( // ErrTemplateContentsAndSource is the error returned when a template // specifies both a "source" and "content" argument, which is not valid. - ErrTemplateContentsAndSource = errors.New("template: cannot specify both 'source' and 'content'") + ErrTemplateContentsAndSource = errors.New("template: cannot specify both 'source' and 'contents'") // ErrTemplateMissingContentsAndSource is the error returned when a template // does not specify either a "source" or "content" argument, which is not // valid. - ErrTemplateMissingContentsAndSource = errors.New("template: must specify exactly one of 'source' or 'content'") + ErrTemplateMissingContentsAndSource = errors.New("template: must specify exactly one of 'source' or 'contents'") ) // Template is the internal representation of an individual template to process. @@ -46,9 +46,9 @@ type Template struct { // is indexed with a key that does not exist. errMissingKey bool - // functionBlacklist are functions not permitted to be executed + // functionDenylist are functions not permitted to be executed // when we render this template - functionBlacklist []string + functionDenylist []string // sandboxPath adds a prefix to any path provided to the `file` function // and causes an error if a relative path tries to traverse outside that @@ -72,9 +72,9 @@ type NewTemplateInput struct { LeftDelim string RightDelim string - // FunctionBlacklist are functions not permitted to be executed + // FunctionDenylist are functions not permitted to be executed // when we render this template - FunctionBlacklist []string + FunctionDenylist []string // SandboxPath adds a prefix to any path provided to the `file` function // and causes an error if a relative path tries to traverse outside that @@ -104,7 +104,7 @@ func NewTemplate(i *NewTemplateInput) (*Template, error) { t.leftDelim = i.LeftDelim t.rightDelim = i.RightDelim t.errMissingKey = i.ErrMissingKey - t.functionBlacklist = i.FunctionBlacklist + t.functionDenylist = i.FunctionDenylist t.sandboxPath = i.SandboxPath if i.Source != "" { @@ -175,13 +175,13 @@ func (t *Template) Execute(i *ExecuteInput) (*ExecuteResult, error) { tmpl.Delims(t.leftDelim, t.rightDelim) tmpl.Funcs(funcMap(&funcMapInput{ - t: tmpl, - brain: i.Brain, - env: i.Env, - used: &used, - missing: &missing, - functionBlacklist: t.functionBlacklist, - sandboxPath: t.sandboxPath, + t: tmpl, + brain: i.Brain, + env: i.Env, + used: &used, + missing: &missing, + functionDenylist: t.functionDenylist, + sandboxPath: t.sandboxPath, })) if t.errMissingKey { @@ -210,13 +210,13 @@ func (t *Template) Execute(i *ExecuteInput) (*ExecuteResult, error) { // funcMapInput is input to the funcMap, which builds the template functions. type funcMapInput struct { - t *template.Template - brain *Brain - env []string - functionBlacklist []string - sandboxPath string - used *dep.Set - missing *dep.Set + t *template.Template + brain *Brain + env []string + functionDenylist []string + sandboxPath string + used *dep.Set + missing *dep.Set } // funcMap is the map of template functions to their respective functions. @@ -273,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, @@ -294,11 +296,13 @@ func funcMap(i *funcMapInput) template.FuncMap { "multiply": multiply, "divide": divide, "modulo": modulo, + "minimum": minimum, + "maximum": maximum, } - for _, bf := range i.functionBlacklist { + for _, bf := range i.functionDenylist { if _, ok := r[bf]; ok { - r[bf] = blacklisted + r[bf] = denied } } diff --git a/vendor/github.com/hashicorp/consul-template/version/version.go b/vendor/github.com/hashicorp/consul-template/version/version.go index d2d876314241..482e3e8453eb 100644 --- a/vendor/github.com/hashicorp/consul-template/version/version.go +++ b/vendor/github.com/hashicorp/consul-template/version/version.go @@ -2,7 +2,7 @@ package version import "fmt" -const Version = "0.24.1" +const Version = "0.25.1" var ( Name string diff --git a/vendor/github.com/hashicorp/consul-template/watch/view.go b/vendor/github.com/hashicorp/consul-template/watch/view.go index 0d7e5fbcdae2..bb5662b9fae2 100644 --- a/vendor/github.com/hashicorp/consul-template/watch/view.go +++ b/vendor/github.com/hashicorp/consul-template/watch/view.go @@ -11,11 +11,6 @@ import ( dep "github.com/hashicorp/consul-template/dependency" ) -const ( - // The amount of time to do a blocking query for - defaultWaitTime = 60 * time.Second -) - // View is a representation of a Dependency and the most recent data it has // received from Consul. type View struct { @@ -33,6 +28,9 @@ type View struct { receivedData bool lastIndex uint64 + // blockQueryWaitTime is amount of time in seconds to do a blocking query for + blockQueryWaitTime time.Duration + // maxStale is the maximum amount of time to allow a query to be stale. maxStale time.Duration @@ -56,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,12 +72,13 @@ type NewViewInput struct { // 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), + dependency: i.Dependency, + clients: i.Clients, + blockQueryWaitTime: i.BlockQueryWaitTime, + maxStale: i.MaxStale, + once: i.Once, + retryFunc: i.RetryFunc, + stopCh: make(chan struct{}, 1), }, nil } @@ -201,7 +203,7 @@ 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, }) if err != nil { diff --git a/vendor/github.com/hashicorp/consul-template/watch/watcher.go b/vendor/github.com/hashicorp/consul-template/watch/watcher.go index 81acd2fe12e5..805740ba5e2b 100644 --- a/vendor/github.com/hashicorp/consul-template/watch/watcher.go +++ b/vendor/github.com/hashicorp/consul-template/watch/watcher.go @@ -27,6 +27,9 @@ type Watcher struct { // errCh is the chan where any errors will be published. errCh chan error + // blockQueryWaitTime is amount of time in seconds to do a blocking query for + blockQueryWaitTime time.Duration + // depViewMap is a map of Templates to Views. Templates are keyed by // their string. depViewMap map[string]*View @@ -54,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,15 +78,16 @@ type NewWatcherInput struct { // 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, + 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 @@ -149,11 +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, + Dependency: d, + Clients: w.clients, + MaxStale: w.maxStale, + BlockQueryWaitTime: w.blockQueryWaitTime, + Once: w.once, + RetryFunc: retryFunc, }) if err != nil { return false, errors.Wrap(err, "watcher") diff --git a/vendor/modules.txt b/vendor/modules.txt index 33ded88c28a1..94d46814cd94 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -341,7 +341,7 @@ github.com/hashicorp/consul/ipaddr github.com/hashicorp/consul/lib github.com/hashicorp/consul/logging github.com/hashicorp/consul/version -# github.com/hashicorp/consul-template v0.24.1 +# github.com/hashicorp/consul-template v0.25.1 ## explicit github.com/hashicorp/consul-template/child github.com/hashicorp/consul-template/config diff --git a/website/pages/docs/configuration/client.mdx b/website/pages/docs/configuration/client.mdx index 40eea277f1f7..d9cdbf3684be 100644 --- a/website/pages/docs/configuration/client.mdx +++ b/website/pages/docs/configuration/client.mdx @@ -139,7 +139,7 @@ driver) but will be removed in a future release. - `cni_config_dir` `(string: "/opt/cni/config")` - Sets the directory where CNI network configuration is located. The client will use this path when fingerprinting CNI networks. - + - `bridge_network name` `(string: "nomad")` - Sets the name of the bridge to be created by nomad for allocations running with bridge networking mode on the client. @@ -343,7 +343,7 @@ see the [drivers documentation](/docs/drivers). ### `template` Parameters -- `function_blacklist` `([]string: ["plugin"])` - Specifies a list of template +- `function_denylist` `([]string: ["plugin"])` - Specifies a list of template rendering functions that should be disallowed in job specs. By default the `plugin` function is disallowed as it allows running arbitrary commands on the host as root (unless Nomad is configured to run as a non-root user).