Merge pull request #5976 from hashicorp/b-consul-template-update-20190718

Update consul-template dependency to latest
This commit is contained in:
Mahmood Ali 2019-07-19 06:49:13 +07:00 committed by GitHub
commit 790e18b973
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 178 additions and 74 deletions

View file

@ -503,7 +503,7 @@ func templateRunner(config *TaskTemplateManagerConfig) (
return nil, nil, err
}
runner, err := manager.NewRunner(runnerConfig, false, false)
runner, err := manager.NewRunner(runnerConfig, false)
if err != nil {
return nil, nil, err
}

View file

@ -1,3 +1,5 @@
## UNRELEASED
## v0.20.0 (February 19, 2019)
IMPROVEMENTS:

View file

@ -3,10 +3,9 @@ MKFILE_PATH := $(lastword $(MAKEFILE_LIST))
CURRENT_DIR := $(patsubst %/,%,$(dir $(realpath $(MKFILE_PATH))))
# Ensure GOPATH
GOPATH ?= $(HOME)/go
# List all our actual files, excluding vendor
GOFILES ?= $(shell go list $(TEST) | grep -v /vendor/)
GOPATH ?= $(shell go env GOPATH)
# assume last entry in GOPATH is home to project
GOPATH := $(lastword $(subst :, ,${GOPATH}))
# Tags specific for building
GOTAGS ?=
@ -15,7 +14,7 @@ GOTAGS ?=
GOMAXPROCS ?= 4
# Get the project metadata
GOVERSION := 1.11.5
GOVERSION := 1.12.5
PROJECT := $(CURRENT_DIR:$(GOPATH)/src/%=%)
OWNER := $(notdir $(patsubst %/,%,$(dir $(PROJECT))))
NAME := $(notdir $(PROJECT))
@ -44,7 +43,7 @@ LD_FLAGS ?= \
-X ${PROJECT}/version.GitCommit=${GIT_COMMIT}
# List of Docker targets to build
DOCKER_TARGETS ?= alpine scratch
DOCKER_TARGETS ?= alpine light scratch
# List of tests to run
TEST ?= ./...
@ -58,13 +57,6 @@ define make-xc-target
@printf "%s%20s %s\n" "-->" "${1}/${2}:" "${PROJECT} (excluded)"
else
@printf "%s%20s %s\n" "-->" "${1}/${2}:" "${PROJECT}"
@docker run \
--interactive \
--rm \
--dns="8.8.8.8" \
--volume="${CURRENT_DIR}:/go/src/${PROJECT}" \
--workdir="/go/src/${PROJECT}" \
"golang:${GOVERSION}" \
env \
CGO_ENABLED="0" \
GOOS="${1}" \
@ -85,6 +77,17 @@ define make-xc-target
endef
$(foreach goarch,$(XC_ARCH),$(foreach goos,$(XC_OS),$(eval $(call make-xc-target,$(goos),$(goarch),$(if $(findstring windows,$(goos)),.exe,)))))
# Use docker to create pristine builds for release
pristine:
@docker run \
--interactive \
--user $$(id -u):$$(id -g) \
--rm \
--dns="8.8.8.8" \
--volume="${CURRENT_DIR}:/go/src/${PROJECT}" \
--workdir="/go/src/${PROJECT}" \
"golang:${GOVERSION}" env GOCACHE=/tmp make -j4 build
# bootstrap installs the necessary go tools for development or build.
bootstrap:
@echo "==> Bootstrapping ${PROJECT}"
@ -114,17 +117,21 @@ dev:
# dist builds the binaries and then signs and packages them for distribution
dist:
@$(MAKE) -f "${MKFILE_PATH}" _cleanup
@$(MAKE) -f "${MKFILE_PATH}" pristine
@$(MAKE) -f "${MKFILE_PATH}" _compress _checksum
.PHONY: dist
release: dist
ifndef GPG_KEY
@echo "==> ERROR: No GPG key specified! Without a GPG key, this release cannot"
@echo " be signed. Set the environment variable GPG_KEY to the ID of"
@echo " the GPG key to continue."
@exit 127
else
@$(MAKE) -f "${MKFILE_PATH}" _cleanup
@$(MAKE) -f "${MKFILE_PATH}" -j4 build
@$(MAKE) -f "${MKFILE_PATH}" _compress _checksum _sign
@$(MAKE) -f "${MKFILE_PATH}" _sign
endif
.PHONY: dist
.PHONY: release
# Create a docker compile and push target for each container. This will create
# docker-build/scratch, docker-push/scratch, etc. It will also create two meta
@ -138,7 +145,6 @@ define make-docker-target
--rm \
--force-rm \
--no-cache \
--squash \
--compress \
--file="docker/${1}/Dockerfile" \
--build-arg="LD_FLAGS=${LD_FLAGS}" \
@ -167,19 +173,23 @@ $(foreach target,$(DOCKER_TARGETS),$(eval $(call make-docker-target,$(target))))
# test runs the test suite.
test:
@echo "==> Testing ${NAME}"
@go test -timeout=30s -parallel=20 -tags="${GOTAGS}" ${GOFILES} ${TESTARGS}
@go test -timeout=30s -parallel=20 -failfast -tags="${GOTAGS}" ./... ${TESTARGS}
.PHONY: test
# test-race runs the test suite.
test-race:
@echo "==> Testing ${NAME} (race)"
@go test -timeout=60s -race -tags="${GOTAGS}" ${GOFILES} ${TESTARGS}
@go test -timeout=60s -race -tags="${GOTAGS}" ./... ${TESTARGS}
.PHONY: test-race
# _cleanup removes any previous binaries
_cleanup:
@rm -rf "${CURRENT_DIR}/pkg/"
@rm -rf "${CURRENT_DIR}/bin/"
.PHONY: _cleanup
clean: _cleanup
.PHONY: clean
# _compress compresses all the binaries in pkg/* as tarball and zip.
_compress:
@ -197,7 +207,7 @@ _compress:
cd "$$platform"; \
tar -czf "${CURRENT_DIR}/pkg/dist/${NAME}_${VERSION}_$${osarch}.tgz" "${NAME}$${ext}"; \
zip -q "${CURRENT_DIR}/pkg/dist/${NAME}_${VERSION}_$${osarch}.zip" "${NAME}$${ext}"; \
cd - &>/dev/null; \
cd - >/dev/null; \
done
.PHONY: _compress
@ -205,7 +215,7 @@ _compress:
_checksum:
@cd "${CURRENT_DIR}/pkg/dist" && \
shasum --algorithm 256 * > ${CURRENT_DIR}/pkg/dist/${NAME}_${VERSION}_SHA256SUMS && \
cd - &>/dev/null
cd - >/dev/null
.PHONY: _checksum
# _sign signs the binaries using the given GPG_KEY. This should not be called

View file

@ -1,6 +1,6 @@
# Consul Template
[![Build Status](http://img.shields.io/travis/hashicorp/consul-template.svg?style=flat-square)](https://travis-ci.org/hashicorp/consul-template)
[![CircleCI](https://circleci.com/gh/hashicorp/consul-template.svg?style=svg)](https://circleci.com/gh/hashicorp/consul-template)
[![Go Documentation](http://img.shields.io/badge/go-documentation-blue.svg?style=flat-square)](https://godoc.org/github.com/hashicorp/consul-template)
This project provides a convenient way to populate values from [Consul][consul]
@ -20,6 +20,20 @@ this functionality might prove useful.
---
## Community Support
If you have questions about how consul-template works, its capabilities or
anything other than a bug or feature request (use github's issue tracker for
those), please see our community support resources.
Community portal: https://discuss.hashicorp.com/c/consul
Other resources: https://www.consul.io/community.html
Additionally, for issues and pull requests, we'll be using the :+1: reactions
as a rough voting system to help gauge community priorities. So please add :+1:
to any issue or pull request you'd like to see worked on. Thanks.
## Installation
@ -967,6 +981,9 @@ This will returns services which are deemed "passing" or "warning" according to
their node and service-level checks defined in Consul. Please note that the
comma implies an "or", not an "and".
**Note:** Due to the use of dot `.` to delimit TAG, the `service` command will
not recognize service names containing dots.
**Note:** There is an architectural difference between the following:
```liquid
@ -980,6 +997,7 @@ and perform client-side filtering. As a general rule, do not use the "passing"
argument alone if you want only healthy services - simply omit the second
argument instead.
##### `services`
Query [Consul][consul] for all services in the catalog.
@ -1476,7 +1494,9 @@ plugin.
{{ plugin "my-plugin" }}
```
This is most commonly combined with a JSON filter for customization:
The plugin can take an arbitrary number of string arguments, and can be the
target of a pipeline that produces strings as well. This is most commonly
combined with a JSON filter for customization:
```liquid
{{ tree "foo" | explode | toJSON | plugin "my-plugin" }}
@ -1777,7 +1797,9 @@ $ NAME [INPUT...]
inherited `PATH` so e.g. the plugin `cat` will run the first executable `cat`
that is found on the `PATH`.
- `INPUT` - input from the template - this will always be JSON if provided
- `INPUT` - input from the template. There will be one INPUT for every argument passed
to the `plugin` function. If the arguments contain whitespace, that whitespace
will be passed as if the argument were quoted by the shell.
#### Important Notes
@ -1788,7 +1810,8 @@ $ NAME [INPUT...]
- Plugin output must be returned as a string on stdout. Only stdout will be
parsed for output. Be sure to log all errors, debugging messages onto stderr
to avoid errors when Consul Template returns the value.
to avoid errors when Consul Template returns the value. Note that output to
stderr will only be output if the plugin returns a non-zero exit code.
- Always `exit 0` or Consul Template will assume the plugin failed to execute
@ -1843,6 +1866,14 @@ func main() {
## Caveats
### Dots in Service Names
Using dots `.` in service names will conflict with the use of dots for [TAG
delineation](https://github.com/hashicorp/consul-template#service) in the
template. Dots already [interfere with using
DNS](https://www.consul.io/docs/agent/services.html#service-and-tag-names-with-dns)
for service names, so we recommend avoiding dots wherever possible.
### Once Mode
In Once mode, Consul Template will wait for all dependencies to be rendered. If
@ -1871,6 +1902,8 @@ loop returns a response. Consul Template waits until it gets a response from
Consul for all dependencies before rendering a template. It does not wait until
that response is non-empty though.
**Note:** Once mode implicitly disables any wait/quiescence timers specified in configuration files or passed on the command line.
### Exec Mode
As of version 0.16.0, Consul Template has the ability to maintain an arbitrary
@ -2191,7 +2224,7 @@ If you want to compile a specific binary, set `XC_OS` and `XC_ARCH` or run the
following to generate all binaries:
```shell
$ make bin
$ make build
```
If you want to run the tests, first [install consul locally](https://www.consul.io/docs/install/index.html), then:

View file

@ -63,7 +63,7 @@ func NewCLI(out, err io.Writer) *CLI {
// status from the command.
func (cli *CLI) Run(args []string) int {
// Parse the flags
config, paths, once, dry, isVersion, err := cli.ParseFlags(args[1:])
config, paths, dry, isVersion, err := cli.ParseFlags(args[1:])
if err != nil {
if err == flag.ErrHelp {
fmt.Fprintf(cli.errStream, usage, version.Name)
@ -103,7 +103,7 @@ func (cli *CLI) Run(args []string) int {
}
// Initial runner
runner, err := manager.NewRunner(config, dry, once)
runner, err := manager.NewRunner(config, dry)
if err != nil {
return logError(err, ExitCodeRunnerError)
}
@ -145,7 +145,7 @@ func (cli *CLI) Run(args []string) int {
return logError(err, ExitCodeConfigError)
}
runner, err = manager.NewRunner(config, dry, once)
runner, err = manager.NewRunner(config, dry)
if err != nil {
return logError(err, ExitCodeRunnerError)
}
@ -188,15 +188,17 @@ func (cli *CLI) stop() {
// Flag library. This is extracted into a helper to keep the main function
// small, but it also makes writing tests for parsing command line arguments
// much easier and cleaner.
func (cli *CLI) ParseFlags(args []string) (*config.Config, []string, bool, bool, bool, error) {
var dry, once, isVersion bool
func (cli *CLI) ParseFlags(args []string) (
*config.Config, []string, bool, bool, error,
) {
var dry, isVersion bool
c := config.DefaultConfig()
if s := os.Getenv("CT_LOCAL_CONFIG"); s != "" {
envConfig, err := config.Parse(s)
if err != nil {
return nil, nil, false, false, false, err
return nil, nil, false, false, err
}
c = c.Merge(envConfig)
}
@ -373,7 +375,10 @@ func (cli *CLI) ParseFlags(args []string) (*config.Config, []string, bool, bool,
return nil
}), "max-stale", "")
flags.BoolVar(&once, "once", false, "")
flags.Var((funcBoolVar)(func(b bool) error {
c.Once = *(config.Bool(b))
return nil
}), "once", "")
flags.Var((funcVar)(func(s string) error {
c.PidFile = config.String(s)
@ -537,16 +542,16 @@ func (cli *CLI) ParseFlags(args []string) (*config.Config, []string, bool, bool,
// If there was a parser error, stop
if err := flags.Parse(args); err != nil {
return nil, nil, false, false, false, err
return nil, nil, false, false, err
}
// Error if extra arguments are present
args = flags.Args()
if len(args) > 0 {
return nil, nil, false, false, false, fmt.Errorf("cli: extra args: %q", args)
return nil, nil, false, false, fmt.Errorf("cli: extra args: %q", args)
}
return c, configPaths, once, dry, isVersion, nil
return c, configPaths, dry, isVersion, nil
}
// loadConfigs loads the configuration from the list of paths. The optional
@ -699,7 +704,7 @@ Options:
distribute work among all servers instead of just the leader
-once
Do not run the process as a daemon
Do not run the process as a daemon. This disables wait/quiescence timers.
-pid-file=<path>
Path on disk to write the PID of the process

View file

@ -6,6 +6,7 @@ import (
"log"
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"syscall"
@ -79,11 +80,18 @@ type Config struct {
// Wait is the quiescence timers.
Wait *WaitConfig `mapstructure:"wait"`
// Additional command line options
// Run once, executing each template exactly once, and exit
Once bool
}
// Copy returns a deep copy of the current configuration. This is useful because
// the nested data structures may be shared.
func (c *Config) Copy() *Config {
if c == nil {
return nil
}
var o Config
o.Consul = c.Consul
@ -126,6 +134,8 @@ func (c *Config) Copy() *Config {
o.Wait = c.Wait.Copy()
}
o.Once = c.Once
return &o
}
@ -193,6 +203,8 @@ func (c *Config) Merge(o *Config) *Config {
r.Wait = r.Wait.Merge(o.Wait)
}
r.Once = o.Once
return r
}
@ -380,7 +392,8 @@ func (c *Config) GoString() string {
"Syslog:%#v, "+
"Templates:%#v, "+
"Vault:%#v, "+
"Wait:%#v"+
"Wait:%#v,"+
"Once:%#v"+
"}",
c.Consul,
c.Dedup,
@ -394,9 +407,31 @@ func (c *Config) GoString() string {
c.Templates,
c.Vault,
c.Wait,
c.Once,
)
}
// Show diff between 2 Configs, useful in tests
func (expected *Config) Diff(actual *Config) string {
var b strings.Builder
fmt.Fprintf(&b, "\n")
ve := reflect.ValueOf(*expected)
va := reflect.ValueOf(*actual)
ct := ve.Type()
for i := 0; i < ve.NumField(); i++ {
fc := ve.Field(i)
fo := va.Field(i)
if !reflect.DeepEqual(fc.Interface(), fo.Interface()) {
fmt.Fprintf(&b, "%s:\n", ct.Field(i).Name)
fmt.Fprintf(&b, "\texp: %#v\n", fc.Interface())
fmt.Fprintf(&b, "\tact: %#v\n", fo.Interface())
}
}
return b.String()
}
// DefaultConfig returns the default configuration struct. Certain environment
// variables may be set which control the values for the default configuration.
func DefaultConfig() *Config {
@ -417,6 +452,9 @@ func DefaultConfig() *Config {
// data was given, but the user did not explicitly add "Enabled: true" to the
// configuration.
func (c *Config) Finalize() {
if c == nil {
return
}
if c.Consul == nil {
c.Consul = DefaultConsulConfig()
}
@ -474,6 +512,11 @@ func (c *Config) Finalize() {
c.Wait = DefaultWaitConfig()
}
c.Wait.Finalize()
// disable Wait if -once was specified
if c.Once {
c.Wait = &WaitConfig{Enabled: Bool(false)}
}
}
func stringFromEnv(list []string, def string) *string {

View file

@ -225,6 +225,12 @@ func isKVv2(client *api.Client, path string) (string, bool, error) {
return "", false, nil
}
// anonymous requests may fail to access /sys/internal/ui path
// Vault v1.1.3 returns 500 status code but may return 4XX in future
if client.Token() == "" {
return "", false, nil
}
return "", false, err
}

View file

@ -19,7 +19,7 @@ import (
consulapi "github.com/hashicorp/consul/api"
)
const (
var (
// sessionCreateRetry is the amount of time we wait
// to recreate a session when lost.
sessionCreateRetry = 15 * time.Second
@ -30,6 +30,12 @@ const (
// listRetry is the interval on which we retry listing a data path
listRetry = 10 * time.Second
// timeout passed through to consul api client Lock
// here to override in testing (see ./dedup_test.go)
lockWaitTime = 15 * time.Second
)
const (
// templateDataFlag is added as a flag to the shared data values
// so that we can use it as a sanity check
templateDataFlag = 0x22b9a127a2c03520
@ -454,6 +460,7 @@ func (d *DedupManager) attemptLock(client *consulapi.Client, session string, ses
Session: session,
MonitorRetries: 3,
MonitorRetryTime: 3 * time.Second,
LockWaitTime: lockWaitTime,
}
lock, err := client.LockOpts(lopts)
if err != nil {

View file

@ -37,10 +37,8 @@ type Runner struct {
// construct other objects and pass data.
config *config.Config
// dry signals that output should be sent to stdout instead of committed to
// disk. once indicates the runner should execute each template exactly one
// time and then stop.
dry, once bool
// signals sending output to STDOUT instead of to a file.
dry bool
// outStream and errStream are the io.Writer streams where the runner will
// write information. These can be modified by calling SetOutStream and
@ -172,13 +170,13 @@ type RenderEvent struct {
// NewRunner accepts a slice of TemplateConfigs and returns a pointer to the new
// Runner and any error that occurred during creation.
func NewRunner(config *config.Config, dry, once bool) (*Runner, error) {
log.Printf("[INFO] (runner) creating new runner (dry: %v, once: %v)", dry, once)
func NewRunner(config *config.Config, dry bool) (*Runner, error) {
log.Printf("[INFO] (runner) creating new runner (dry: %v, once: %v)",
dry, config.Once)
runner := &Runner{
config: config,
dry: dry,
once: once,
}
if err := runner.init(); err != nil {
@ -305,7 +303,7 @@ func (r *Runner) Start() {
// If we are running in once mode and all our templates are rendered,
// then we should exit here.
if r.once {
if r.config.Once {
log.Printf("[INFO] (runner) once mode and all templates rendered")
if r.child != nil {
@ -653,7 +651,7 @@ func (r *Runner) runTemplate(tmpl *template.Template, runCtx *templateRunCtx) (*
// If we are in once mode and this template was already rendered, move
// onto the next one. We do not want to re-render the template if we are
// in once mode, and we certainly do not want to re-run any commands.
if r.once {
if r.config.Once {
r.renderEventsLock.RLock()
event, ok := r.renderEvents[tmpl.ID()]
r.renderEventsLock.RUnlock()
@ -836,7 +834,7 @@ func (r *Runner) init() error {
}
// Create the watcher
watcher, err := newWatcher(r.config, clients, r.once)
watcher, err := newWatcher(r.config, clients, r.config.Once)
if err != nil {
return fmt.Errorf("runner: %s", err)
}
@ -895,7 +893,7 @@ func (r *Runner) init() error {
r.quiescenceCh = make(chan *template.Template)
if *r.config.Dedup.Enabled {
if r.once {
if r.config.Once {
log.Printf("[INFO] (runner) disabling de-duplication in once mode")
} else {
r.dedup, err = NewDedupManager(r.config.Dedup, clients, r.brain, r.templates)
@ -1269,7 +1267,7 @@ func newWatcher(c *config.Config, clients *dep.ClientSet, once bool) (*watch.Wat
w, err := watch.NewWatcher(&watch.NewWatcherInput{
Clients: clients,
MaxStale: config.TimeDurationVal(c.MaxStale),
Once: once,
Once: c.Once,
RenewVault: clients.Vault().Token() != "" && config.BoolVal(c.Vault.RenewToken),
VaultAgentTokenFile: config.StringVal(c.Vault.VaultAgentTokenFile),
RetryFuncConsul: watch.RetryFunc(c.Consul.Retry.RetryFunc()),

View file

@ -2,7 +2,7 @@ package version
import "fmt"
const Version = "0.20.0"
const Version = "0.20.1-dev"
var (
Name string

22
vendor/vendor.json vendored
View file

@ -157,17 +157,17 @@
{"path":"github.com/gorilla/context","checksumSHA1":"g/V4qrXjUGG9B+e3hB+4NAYJ5Gs=","revision":"08b5f424b9271eedf6f9f0ce86cb9396ed337a42","revisionTime":"2016-08-17T18:46:32Z"},
{"path":"github.com/gorilla/mux","checksumSHA1":"STQSdSj2FcpCf0NLfdsKhNutQT0=","revision":"e48e440e4c92e3251d812f8ce7858944dfa3331c","revisionTime":"2018-08-07T07:52:56Z"},
{"path":"github.com/gorilla/websocket","checksumSHA1":"gr0edNJuVv4+olNNZl5ZmwLgscA=","revision":"0ec3d1bd7fe50c503d6df98ee649d81f4857c564","revisionTime":"2019-03-06T00:42:57Z"},
{"path":"github.com/hashicorp/consul-template","checksumSHA1":"+AGSqY+9kpGX5rrQDBWpgzaDKSA=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/child","checksumSHA1":"AhDPiKa7wzh3SE6Gx0WrsDYwBHg=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/config","checksumSHA1":"0vr6paBMXD7ZYSmtfJpjfjZJKic=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/dependency","checksumSHA1":"PYz8+xNjJkv+pyqo/d5f2qVSH+w=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/logging","checksumSHA1":"o5N7SV389Ej+3b1iRNmz1dx5e1M=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/manager","checksumSHA1":"FXkwzbFD6/LTHyf8bjpgxGvFXOE=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/renderer","checksumSHA1":"DUHtghMoLyrgPhv4lexVniBuWYk=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/signals","checksumSHA1":"YSEUV/9/k85XciRKu0cngxdjZLE=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/template","checksumSHA1":"Y0Ws3O64np8sFDE/3vAx8lFUHxc=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/version","checksumSHA1":"RbpOltpZ0PLi1NA6Senz9sWFRSc=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template/watch","checksumSHA1":"cJxopvJKg7DBBb8tnDsfmBp5Q8I=","revision":"9a0f301b69d841c32f36b78008afb2dee8a9c40b","revisionTime":"2019-02-20T00:40:33Z"},
{"path":"github.com/hashicorp/consul-template","checksumSHA1":"k5zZ8xCgta0EJ2sZWPEs1kAM5Vw=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/child","checksumSHA1":"AhDPiKa7wzh3SE6Gx0WrsDYwBHg=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/config","checksumSHA1":"BIIejfVMt8xA1bGtJswPpT+wwMA=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/dependency","checksumSHA1":"kMdbOWSNfm8Imce6y6cweX+EVNg=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/logging","checksumSHA1":"o5N7SV389Ej+3b1iRNmz1dx5e1M=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/manager","checksumSHA1":"9lrVI3BnWtC5Z2l/LXdK0e2yJjI=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/renderer","checksumSHA1":"DUHtghMoLyrgPhv4lexVniBuWYk=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/signals","checksumSHA1":"YSEUV/9/k85XciRKu0cngxdjZLE=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/template","checksumSHA1":"Y0Ws3O64np8sFDE/3vAx8lFUHxc=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/version","checksumSHA1":"85qK+LAbb/oAjvdDqVOLi4tMxZk=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul-template/watch","checksumSHA1":"cJxopvJKg7DBBb8tnDsfmBp5Q8I=","revision":"4058b146979c4feb0551d39b8795a31409b3e6bf","revisionTime":"2019-07-17T18:51:08Z"},
{"path":"github.com/hashicorp/consul/agent/consul/autopilot","checksumSHA1":"+I7fgoQlrnTUGW5krqNLadWwtjg=","revision":"fb848fc48818f58690db09d14640513aa6bf3c02","revisionTime":"2018-04-13T17:05:42Z"},
{"path":"github.com/hashicorp/consul/api","checksumSHA1":"sjEf6EMTPP4NT3m5a0JJmlbLZ8Y=","revision":"39f93f011e591c842acc8053a7f5972aa6e592fd","revisionTime":"2018-07-12T16:33:56Z"},
{"path":"github.com/hashicorp/consul/command/flags","checksumSHA1":"soNN4xaHTbeXFgNkZ7cX0gbFXQk=","revision":"fb848fc48818f58690db09d14640513aa6bf3c02","revisionTime":"2018-04-13T17:05:42Z"},