hashicorp / consul-template

Template rendering, notifier, and supervisor for @HashiCorp Consul and Vault data.
https://www.hashicorp.com/
Mozilla Public License 2.0
4.76k stars 782 forks source link

Template timestamp causes continuous regeneration #873

Closed taharah closed 7 years ago

taharah commented 7 years ago

When using {{timestamp}} in a template it constantly re-renders the template. I would like to see a new timestamp since that is ever changing not trigger a template generation.

sethvargo commented 7 years ago

Hi @taharah

Could you please share your complete template as well as the output in debug mode?

taharah commented 7 years ago

Consul Template version

consul-template v0.18.0 (5211c66)

Configuration

{
  "consul": {
    "address": "127.0.0.1:8500",
    "retry": {
      "enabled": true,
      "attempts": -1,
      "backoff": "250ms"
    }
  },
  "max_stale": "2m",
  "log_level": "info",
  "wait": {
    "min": "1m",
    "max": "2m"
  },
  "deduplicate": {
    "enabled": true,
    "prefix": "consul-template/dedup/"
  }
}

Command

/usr/local/bin/consul-template -config /etc/consul-template.d

Debug output

https://gist.github.com/taharah/1f9e7fb4a9310b3d3d54e09bc9c44a78

# {{print "RENDERED: "}}{{timestamp}}
{{range $client, $pairs := tree "clients" | byKey -}}
{{$client}}_solr  {{$client | toLower}}_solr
{{$shards := (print "clients/" $client "/shards_total") | key | parseInt | add 1 -}}
{{range $num := loop 1 $shards -}}{{$client}}_solr{{$num}} {{$client | toLower}}_solr{{$num}}
{{end}}{{end -}}
{{$client := "client3" -}}
{{$check := "check on-error mark-down observe layer7 error-limit 1" -}}
# {{print "RENDERED:\t"}}{{timestamp}}
# {{print "MNEMONIC:\t"}}{{ (print "clients/" $client "/mnemonic") | key }}
# {{print "DOMAIN:\t"}}{{ (print "clients/" $client "/domain") | key }}
backend {{$client | toLower}}_solr
{{range service $client -}}
{{"  "}}server {{.ID}} {{.Address}}:{{.Port}} {{$check}} weight {{if .Tags | contains "master"}}1{{else}}256{{end}}
{{end -}}

{{- $shards := (print "clients/" $client "/shards_total") | key | parseInt | add 1 -}}
{{range $num := loop 1 $shards -}}
{{$shard := (print "solr" $num) -}}
backend {{$client | toLower}}_{{$shard}}
  reqirep (.*[A-Z_]+solr)(?:[0-9]+)(.*)    \1\2
{{range service (print $shard "." $client) -}}
{{"  "}}server {{.ID}} {{.Address}}:{{.Port}} {{$check}} weight {{if .Tags | contains "master"}}1{{else}}256{{end}}
{{end -}}
{{end -}}

Expected behavior

It should not have rendered a new template just because the timestamp changed.

Actual behavior

It rendered a new template since the timestamp changed. It looks like this issue might be hard to fix since as far as I can tell it's just comparing hashes of the new and old renderings.

Steps to reproduce

  1. Use any template with a timestamp in it.
sethvargo commented 7 years ago

Hi @taharah

I just tried, and I'm unable to reproduce this. It's true that the timestamp will render when the new version changes, but it only renders when other dependencies change. You can verify this with a small template:

{{ timestamp }}
{{ key "foo" }}

That small template will not re-render regardless of the timestamp call. I've tried with and without dedup mode.

If you run in TRACE mode, there will be a lot of log output, but it will tell you which dependency is causing the template to change.

You're right that the files are compared using a hash, but they are only compared after a dependency has changed. One of the keys/services/etc is changing, resulting in the template to trigger a re-render.

taharah commented 7 years ago

Hmm alright I'll take a look in trace mode and report back. I was able to get the continuous rendering to stop once I removed the timestamp for the time being.

taharah commented 7 years ago

I added the timestamp function back to only a single template and it was not that template that was re-rendering. So closing this out as it appears to be working as expected.

legege commented 5 years ago

We have exactly this problem. The problem can easily be reproduced with Consul Template 0.21.3:

  1. Use config with "wait" (min and max correctly set)
  2. Use timestamp in the template
  3. Restart consul-template
  4. Observe that consul-template is NOT rerendering every "min" seconds.
  5. Trigger a template reload (e.g. shutdown a service if you use service state in your template)
  6. Observe that consul-template IS rerendering every "min" seconds.
faryon93 commented 5 months ago

I'm experiencing the same behaviour as @legege with a template in nomad. Did anyone found a solution to this problem?